blob: e7bca1897dedec0912955f31b3f71e6beb2abc8e [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>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Christopher Faulet4fce0d82017-09-18 11:57:31 +020057#include <proto/action.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010058#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020060#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020062#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020063#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010064#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020065#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020066#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020067#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020068#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010069#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020070#include <proto/lb_fwlc.h>
71#include <proto/lb_fwrr.h>
72#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020075#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010083#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010084#include <proto/task.h>
85#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
87
Willy Tarreauf3c69202006-07-09 16:42:34 +020088/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
89 * ssl-hello-chk option to ensure that the remote server speaks SSL.
90 *
91 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
92 */
93const char sslv3_client_hello_pkt[] = {
94 "\x16" /* ContentType : 0x16 = Hanshake */
95 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
96 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
97 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
98 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
99 "\x03\x00" /* Hello Version : 0x0300 = v3 */
100 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
101 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
102 "\x00" /* Session ID length : empty (no session ID) */
103 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
104 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
105 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
106 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
107 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
108 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
109 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
110 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
111 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
112 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
113 "\x00\x38" "\x00\x39" "\x00\x3A"
114 "\x01" /* Compression Length : 0x01 = 1 byte for types */
115 "\x00" /* Compression Type : 0x00 = NULL compression */
116};
117
Willy Tarreau3842f002009-06-14 11:39:52 +0200118/* various keyword modifiers */
119enum kw_mod {
120 KWM_STD = 0, /* normal */
121 KWM_NO, /* "no" prefixed before the keyword */
122 KWM_DEF, /* "default" prefixed before the keyword */
123};
124
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100125/* permit to store configuration section */
126struct cfg_section {
127 struct list list;
128 char *section_name;
129 int (*section_parser)(const char *, int, char **, int);
William Lallemandd2ff56d2017-10-16 11:06:50 +0200130 int (*post_section_parser)();
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
William Lallemand48b4bb42017-10-23 14:36:34 +0200138/* store post configuration parsing */
139
140struct cfg_postparser {
141 struct list list;
142 char *name;
143 int (*func)();
144};
145
146struct list postparsers = LIST_HEAD_INIT(postparsers);
147
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100149struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150 const char *name;
151 unsigned int val;
152 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100153 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100155};
156
157/* proxy->options */
158static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100159{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
161 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
162 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
163 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
164 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
165 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200167 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200168 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100169 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
171 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
172 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100174#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100175 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100176#else
177 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100178#endif
179
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100180 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100181};
182
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100183/* proxy->options2 */
184static const struct cfg_opt cfg_opts2[] =
185{
186#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100187 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
188 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
189 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100190#else
191 { "splice-request", 0, 0, 0, 0 },
192 { "splice-response", 0, 0, 0, 0 },
193 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100194#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
196 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
197 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
198 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
199 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
200 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
201 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
202 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
203 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400204 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100205 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200206 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200207 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100208 { NULL, 0, 0, 0 }
209};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
Willy Tarreau6daf3432008-01-22 16:44:08 +0100211static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
213int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100214int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100215char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200217/* List head of all known configuration keywords */
218static struct cfg_kw_list cfg_keywords = {
219 .list = LIST_HEAD_INIT(cfg_keywords.list)
220};
221
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222/*
223 * converts <str> to a list of listeners which are dynamically allocated.
224 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
225 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
226 * - <port> is a numerical port from 1 to 65535 ;
227 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
228 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200229 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
230 * not NULL, it must be a valid pointer to either NULL or a freeable area that
231 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200233int 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 +0200234{
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100235 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 int port, end;
237
238 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200239
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 while (next && *next) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200241 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100242 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
244 str = next;
245 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100246 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247 *next++ = 0;
248 }
249
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100250 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200251 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200252 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100253 if (!ss2)
254 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100256 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100257 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100259 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100262 if (!port || !end) {
263 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
264 goto fail;
265 }
266
Emeric Bruned760922010-10-22 17:59:25 +0200267 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200268 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200269 goto fail;
270 }
271
272 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200273 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200274 goto fail;
275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100277 else if (ss2->ss_family == AF_UNSPEC) {
278 socklen_t addr_len;
279
280 /* We want to attach to an already bound fd whose number
281 * is in the addr part of ss2 when cast to sockaddr_in.
282 * Note that by definition there is a single listener.
283 * We still have to determine the address family to
284 * register the correct protocol.
285 */
286 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
287 addr_len = sizeof(*ss2);
288 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
289 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
290 goto fail;
291 }
292
293 port = end = get_host_port(ss2);
294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100296 /* OK the address looks correct */
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200297 if (!create_listeners(bind_conf, ss2, port, end, fd, err)) {
298 memprintf(err, "%s for address '%s'.\n", *err, str);
299 goto fail;
300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 } /* end while(next) */
302 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200303 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 fail:
305 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200306 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307}
308
William Lallemand6e62fb62015-04-28 16:55:23 +0200309/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100310 * Report an error in <msg> when there are too many arguments. This version is
311 * intended to be used by keyword parsers so that the message will be included
312 * into the general error message. The index is the current keyword in args.
313 * Return 0 if the number of argument is correct, otherwise build a message and
314 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
315 * message may also be null, it will simply not be produced (useful to check only).
316 * <msg> and <err_code> are only affected on error.
317 */
318int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
319{
320 int i;
321
322 if (!*args[index + maxarg + 1])
323 return 0;
324
325 if (msg) {
326 *msg = NULL;
327 memprintf(msg, "%s", args[0]);
328 for (i = 1; i <= index; i++)
329 memprintf(msg, "%s %s", *msg, args[i]);
330
331 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
332 }
333 if (err_code)
334 *err_code |= ERR_ALERT | ERR_FATAL;
335
336 return 1;
337}
338
339/*
340 * same as too_many_args_idx with a 0 index
341 */
342int too_many_args(int maxarg, char **args, char **msg, int *err_code)
343{
344 return too_many_args_idx(maxarg, 0, args, msg, err_code);
345}
346
347/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200348 * Report a fatal Alert when there is too much arguments
349 * The index is the current keyword in args
350 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
351 * Fill err_code with an ERR_ALERT and an ERR_FATAL
352 */
353int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
354{
355 char *kw = NULL;
356 int i;
357
358 if (!*args[index + maxarg + 1])
359 return 0;
360
361 memprintf(&kw, "%s", args[0]);
362 for (i = 1; i <= index; i++) {
363 memprintf(&kw, "%s %s", kw, args[i]);
364 }
365
366 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
367 free(kw);
368 *err_code |= ERR_ALERT | ERR_FATAL;
369 return 1;
370}
371
372/*
373 * same as alertif_too_many_args_idx with a 0 index
374 */
375int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
376{
377 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
378}
379
Willy Tarreau620408f2016-10-21 16:37:51 +0200380/* Report a warning if a rule is placed after a 'tcp-request session' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
383int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
384{
385 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200393/* Report a warning if a rule is placed after a 'tcp-request content' rule.
394 * Return 1 if the warning has been emitted, otherwise 0.
395 */
396int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
397{
398 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
399 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
400 file, line, arg);
401 return 1;
402 }
403 return 0;
404}
405
Willy Tarreau61d18892009-03-31 10:49:21 +0200406/* Report a warning if a rule is placed after a 'block' rule.
407 * Return 1 if the warning has been emitted, otherwise 0.
408 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100409int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200410{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200411 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200412 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
413 file, line, arg);
414 return 1;
415 }
416 return 0;
417}
418
Willy Tarreau5002f572014-04-23 01:32:02 +0200419/* Report a warning if a rule is placed after an 'http_request' rule.
420 * Return 1 if the warning has been emitted, otherwise 0.
421 */
422int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
423{
424 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
425 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
426 file, line, arg);
427 return 1;
428 }
429 return 0;
430}
431
Willy Tarreau61d18892009-03-31 10:49:21 +0200432/* Report a warning if a rule is placed after a reqrewrite rule.
433 * Return 1 if the warning has been emitted, otherwise 0.
434 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100435int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200436{
437 if (proxy->req_exp) {
438 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
439 file, line, arg);
440 return 1;
441 }
442 return 0;
443}
444
445/* Report a warning if a rule is placed after a reqadd rule.
446 * Return 1 if the warning has been emitted, otherwise 0.
447 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100448int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200449{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100450 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200451 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
452 file, line, arg);
453 return 1;
454 }
455 return 0;
456}
457
458/* Report a warning if a rule is placed after a redirect rule.
459 * Return 1 if the warning has been emitted, otherwise 0.
460 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100461int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200462{
463 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
464 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
465 file, line, arg);
466 return 1;
467 }
468 return 0;
469}
470
471/* Report a warning if a rule is placed after a 'use_backend' rule.
472 * Return 1 if the warning has been emitted, otherwise 0.
473 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100474int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200475{
476 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
477 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
478 file, line, arg);
479 return 1;
480 }
481 return 0;
482}
483
Willy Tarreauee445d92014-04-23 01:39:04 +0200484/* Report a warning if a rule is placed after a 'use-server' rule.
485 * Return 1 if the warning has been emitted, otherwise 0.
486 */
487int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
488{
489 if (!LIST_ISEMPTY(&proxy->server_rules)) {
490 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
491 file, line, arg);
492 return 1;
493 }
494 return 0;
495}
496
Willy Tarreaud39ad442016-11-25 15:16:12 +0100497/* report a warning if a redirect rule is dangerously placed */
498int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200499{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100500 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200501 warnif_rule_after_use_server(proxy, file, line, arg);
502}
503
Willy Tarreaud39ad442016-11-25 15:16:12 +0100504/* report a warning if a reqadd rule is dangerously placed */
505int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200506{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100507 return warnif_rule_after_redirect(proxy, file, line, arg) ||
508 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200509}
510
Willy Tarreaud39ad442016-11-25 15:16:12 +0100511/* report a warning if a reqxxx rule is dangerously placed */
512int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200513{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100514 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
515 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200516}
517
518/* report a warning if an http-request rule is dangerously placed */
519int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
520{
Willy Tarreau61d18892009-03-31 10:49:21 +0200521 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200523}
524
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525/* report a warning if a block rule is dangerously placed */
526int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200527{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100528 return warnif_rule_after_http_req(proxy, file, line, arg) ||
529 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200530}
531
Willy Tarreaud39ad442016-11-25 15:16:12 +0100532/* report a warning if a "tcp request content" rule is dangerously placed */
533int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200534{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100535 return warnif_rule_after_block(proxy, file, line, arg) ||
536 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200537}
538
Willy Tarreaud39ad442016-11-25 15:16:12 +0100539/* report a warning if a "tcp request session" rule is dangerously placed */
540int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200541{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
543 warnif_misplaced_tcp_cont(proxy, file, line, arg);
544}
545
546/* report a warning if a "tcp request connection" rule is dangerously placed */
547int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
548{
549 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
550 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200551}
552
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100553/* Report it if a request ACL condition uses some keywords that are incompatible
554 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
555 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
556 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100557 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100558static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100559{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100560 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200561 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100562
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100563 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100564 return 0;
565
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566 acl = acl_cond_conflicts(cond, where);
567 if (acl) {
568 if (acl->name && *acl->name)
569 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
570 file, line, acl->name, sample_ckp_names(where));
571 else
572 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 +0200573 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100574 return ERR_WARN;
575 }
576 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100577 return 0;
578
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100579 if (acl->name && *acl->name)
580 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200581 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 else
583 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200584 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100585 return ERR_WARN;
586}
587
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200589 * parse a line in a <global> section. Returns the error code, 0 if OK, or
590 * any combination of :
591 * - ERR_ABORT: must abort ASAP
592 * - ERR_FATAL: we can continue parsing but not start the service
593 * - ERR_WARN: a warning has been emitted
594 * - ERR_ALERT: an alert has been emitted
595 * Only the two first ones can stop processing, the two others are just
596 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200598int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599{
Willy Tarreau058e9072009-07-20 09:30:05 +0200600 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200601 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602
603 if (!strcmp(args[0], "global")) { /* new section */
604 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200605 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 }
608 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200609 if (alertif_too_many_args(0, file, linenum, args, &err_code))
610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 global.mode |= MODE_DAEMON;
612 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200613 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200614 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200615 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200616 if (*args[1]) {
617 if (!strcmp(args[1], "exit-on-failure")) {
618 global.tune.options |= GTUNE_EXIT_ONFAILURE;
619 } else {
620 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
623 }
624 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200625 global.mode |= MODE_MWORKER;
626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200628 if (alertif_too_many_args(0, file, linenum, args, &err_code))
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 global.mode |= MODE_DEBUG;
631 }
632 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100635 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200637 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100640 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "nopoll")) {
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_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100647 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100650 global.tune.options &= ~GTUNE_USE_SPLICE;
651 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200652 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200655 global.tune.options &= ~GTUNE_USE_GAI;
656 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000657 else if (!strcmp(args[0], "noreuseport")) {
658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
660 global.tune.options &= ~GTUNE_USE_REUSEPORT;
661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 global.mode |= MODE_QUIET;
666 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200667 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(1, file, linenum, args, &err_code))
669 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 if (global.tune.maxpollevents != 0) {
671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT;
673 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200674 }
675 if (*(args[1]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 global.tune.maxpollevents = atol(args[1]);
681 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100682 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 if (global.tune.maxaccept != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 global.tune.maxaccept = atol(args[1]);
696 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200697 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.chksize = atol(args[1]);
706 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100707 else if (!strcmp(args[0], "tune.recv_enough")) {
708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
709 goto out;
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 global.tune.recv_enough = atol(args[1]);
716 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100717 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
719 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100720 if (*(args[1]) == 0) {
721 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
722 err_code |= ERR_ALERT | ERR_FATAL;
723 goto out;
724 }
725 global.tune.buf_limit = atol(args[1]);
726 if (global.tune.buf_limit) {
727 if (global.tune.buf_limit < 3)
728 global.tune.buf_limit = 3;
729 if (global.tune.buf_limit <= global.tune.reserved_bufs)
730 global.tune.buf_limit = global.tune.reserved_bufs + 1;
731 }
732 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100733 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741 global.tune.reserved_bufs = atol(args[1]);
742 if (global.tune.reserved_bufs < 2)
743 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100744 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100746 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200747 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200756 if (global.tune.bufsize <= 0) {
757 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
760 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200761 }
762 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
764 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200771 if (global.tune.maxrewrite < 0) {
772 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200776 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100777 else if (!strcmp(args[0], "tune.idletimer")) {
778 unsigned int idle;
779 const char *res;
780
William Lallemand1a748ae2015-05-19 16:37:23 +0200781 if (alertif_too_many_args(1, file, linenum, args, &err_code))
782 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100783 if (*(args[1]) == 0) {
784 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788
789 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
790 if (res) {
791 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
792 file, linenum, *res, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796
797 if (idle > 65535) {
798 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802 global.tune.idle_timer = idle;
803 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100804 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100807 if (global.tune.client_rcvbuf != 0) {
808 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT;
810 goto out;
811 }
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.client_rcvbuf = atol(args[1]);
818 }
819 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200820 if (alertif_too_many_args(1, file, linenum, args, &err_code))
821 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100822 if (global.tune.server_rcvbuf != 0) {
823 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
824 err_code |= ERR_ALERT;
825 goto out;
826 }
827 if (*(args[1]) == 0) {
828 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 global.tune.server_rcvbuf = atol(args[1]);
833 }
834 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200835 if (alertif_too_many_args(1, file, linenum, args, &err_code))
836 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100837 if (global.tune.client_sndbuf != 0) {
838 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT;
840 goto out;
841 }
842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.client_sndbuf = atol(args[1]);
848 }
849 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200850 if (alertif_too_many_args(1, file, linenum, args, &err_code))
851 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100852 if (global.tune.server_sndbuf != 0) {
853 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT;
855 goto out;
856 }
857 if (*(args[1]) == 0) {
858 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
861 }
862 global.tune.server_sndbuf = atol(args[1]);
863 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200864 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200865 if (alertif_too_many_args(1, file, linenum, args, &err_code))
866 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200867 if (*(args[1]) == 0) {
868 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872 global.tune.pipesize = atol(args[1]);
873 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100874 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200875 if (alertif_too_many_args(1, file, linenum, args, &err_code))
876 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.tune.cookie_len = atol(args[1]) + 1;
883 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200884 else if (!strcmp(args[0], "tune.http.logurilen")) {
885 if (alertif_too_many_args(1, file, linenum, args, &err_code))
886 goto out;
887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892 global.tune.requri_len = atol(args[1]) + 1;
893 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200894 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200895 if (alertif_too_many_args(1, file, linenum, args, &err_code))
896 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200897 if (*(args[1]) == 0) {
898 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200902 global.tune.max_http_hdr = atoi(args[1]);
903 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
904 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
905 file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200909 }
William Lallemandf3747832012-11-09 12:33:10 +0100910 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200911 if (alertif_too_many_args(1, file, linenum, args, &err_code))
912 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100913 if (*args[1]) {
914 global.tune.comp_maxlevel = atoi(args[1]);
915 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
916 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
917 file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 } else {
922 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
923 file, linenum, args[0]);
924 err_code |= ERR_ALERT | ERR_FATAL;
925 goto out;
926 }
927 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200928 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
929 if (*args[1]) {
930 global.tune.pattern_cache = atoi(args[1]);
931 if (global.tune.pattern_cache < 0) {
932 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
933 file, linenum, args[0]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 } else {
938 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
939 file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200945 if (alertif_too_many_args(1, file, linenum, args, &err_code))
946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200948 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT;
950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100957 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
958 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
959 err_code |= ERR_WARN;
960 goto out;
961 }
962
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200965 if (alertif_too_many_args(1, file, linenum, args, &err_code))
966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200968 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200969 err_code |= ERR_ALERT;
970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 }
972 if (*(args[1]) == 0) {
973 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100977 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
978 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
979 err_code |= ERR_WARN;
980 goto out;
981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 }
Simon Horman98637e52014-06-20 12:30:16 +0900983 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200984 if (alertif_too_many_args(0, file, linenum, args, &err_code))
985 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900986 global.external_check = 1;
987 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200988 /* user/group name handling */
989 else if (!strcmp(args[0], "user")) {
990 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200991 if (alertif_too_many_args(1, file, linenum, args, &err_code))
992 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200993 if (global.uid != 0) {
994 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200997 }
998 errno = 0;
999 ha_user = getpwnam(args[1]);
1000 if (ha_user != NULL) {
1001 global.uid = (int)ha_user->pw_uid;
1002 }
1003 else {
1004 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 +02001005 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001006 }
1007 }
1008 else if (!strcmp(args[0], "group")) {
1009 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001010 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1011 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001012 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001013 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT;
1015 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001016 }
1017 errno = 0;
1018 ha_group = getgrnam(args[1]);
1019 if (ha_group != NULL) {
1020 global.gid = (int)ha_group->gr_gid;
1021 }
1022 else {
1023 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 +02001024 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001025 }
1026 }
1027 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001029 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 if (*(args[1]) == 0) {
1032 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 }
1036 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001037 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1038 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1039 file, linenum, args[0], LONGBITS, global.nbproc);
1040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
1042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 }
1044 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001045 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 if (global.maxconn != 0) {
1048 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 err_code |= ERR_ALERT;
1050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052 if (*(args[1]) == 0) {
1053 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
1057 global.maxconn = atol(args[1]);
1058#ifdef SYSTEM_MAXCONN
1059 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1060 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);
1061 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001062 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 }
1064#endif /* SYSTEM_MAXCONN */
1065 }
Emeric Brun850efd52014-01-29 12:24:34 +01001066 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001067 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1068 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074 if (strcmp(args[1],"none") == 0)
1075 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1076 else if (strcmp(args[1],"required") == 0)
1077 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1078 else {
1079 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
1082 }
1083 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001084 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001085 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1086 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001087 if (global.cps_lim != 0) {
1088 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1089 err_code |= ERR_ALERT;
1090 goto out;
1091 }
1092 if (*(args[1]) == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097 global.cps_lim = atol(args[1]);
1098 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001099 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001100 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1101 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001102 if (global.sps_lim != 0) {
1103 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1104 err_code |= ERR_ALERT;
1105 goto out;
1106 }
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 global.sps_lim = atol(args[1]);
1113 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001114 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001115 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1116 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001117 if (global.ssl_lim != 0) {
1118 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1119 err_code |= ERR_ALERT;
1120 goto out;
1121 }
1122 if (*(args[1]) == 0) {
1123 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto out;
1126 }
1127 global.ssl_lim = atol(args[1]);
1128 }
William Lallemandd85f9172012-11-09 17:05:39 +01001129 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001130 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1131 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001132 if (*(args[1]) == 0) {
1133 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto out;
1136 }
1137 global.comp_rate_lim = atoi(args[1]) * 1024;
1138 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001139 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001140 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1141 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001142 if (global.maxpipes != 0) {
1143 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001144 err_code |= ERR_ALERT;
1145 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001146 }
1147 if (*(args[1]) == 0) {
1148 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001151 }
1152 global.maxpipes = atol(args[1]);
1153 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001154 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001155 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1156 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001157 if (*(args[1]) == 0) {
1158 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
1161 }
William Lallemande3a7d992012-11-20 11:25:20 +01001162 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001163 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001164 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001165 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1166 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001167 if (*(args[1]) == 0) {
1168 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto out;
1171 }
1172 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001173 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001174 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
1177 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001178 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001179
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001181 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 if (global.rlimit_nofile != 0) {
1184 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001185 err_code |= ERR_ALERT;
1186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 }
1188 if (*(args[1]) == 0) {
1189 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192 }
1193 global.rlimit_nofile = atol(args[1]);
1194 }
1195 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 if (global.chroot != NULL) {
1199 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 }
1208 global.chroot = strdup(args[1]);
1209 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001210 else if (!strcmp(args[0], "description")) {
1211 int i, len=0;
1212 char *d;
1213
1214 if (!*args[1]) {
1215 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1216 file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220
Willy Tarreau348acfe2014-04-14 15:00:39 +02001221 for (i = 1; *args[i]; i++)
1222 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001223
1224 if (global.desc)
1225 free(global.desc);
1226
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001227 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001228
Willy Tarreau348acfe2014-04-14 15:00:39 +02001229 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1230 for (i = 2; *args[i]; i++)
1231 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001232 }
1233 else if (!strcmp(args[0], "node")) {
1234 int i;
1235 char c;
1236
William Lallemand1a748ae2015-05-19 16:37:23 +02001237 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1238 goto out;
1239
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001240 for (i=0; args[1][i]; i++) {
1241 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001242 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1243 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001244 break;
1245 }
1246
1247 if (!i || args[1][i]) {
1248 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1249 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1250 file, linenum, args[0]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
1254
1255 if (global.node)
1256 free(global.node);
1257
1258 global.node = strdup(args[1]);
1259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001261 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 if (global.pidfile != NULL) {
1264 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001265 err_code |= ERR_ALERT;
1266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268 if (*(args[1]) == 0) {
1269 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 }
1273 global.pidfile = strdup(args[1]);
1274 }
Emeric Bruned760922010-10-22 17:59:25 +02001275 else if (!strcmp(args[0], "unix-bind")) {
1276 int cur_arg = 1;
1277 while (*(args[cur_arg])) {
1278 if (!strcmp(args[cur_arg], "prefix")) {
1279 if (global.unix_bind.prefix != NULL) {
1280 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1281 err_code |= ERR_ALERT;
1282 cur_arg += 2;
1283 continue;
1284 }
1285
1286 if (*(args[cur_arg+1]) == 0) {
1287 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
1290 }
1291 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (!strcmp(args[cur_arg], "mode")) {
1297
1298 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (!strcmp(args[cur_arg], "uid")) {
1304
1305 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1306 cur_arg += 2;
1307 continue;
1308 }
1309
1310 if (!strcmp(args[cur_arg], "gid")) {
1311
1312 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1313 cur_arg += 2;
1314 continue;
1315 }
1316
1317 if (!strcmp(args[cur_arg], "user")) {
1318 struct passwd *user;
1319
1320 user = getpwnam(args[cur_arg + 1]);
1321 if (!user) {
1322 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1323 file, linenum, args[0], args[cur_arg + 1 ]);
1324 err_code |= ERR_ALERT | ERR_FATAL;
1325 goto out;
1326 }
1327
1328 global.unix_bind.ux.uid = user->pw_uid;
1329 cur_arg += 2;
1330 continue;
1331 }
1332
1333 if (!strcmp(args[cur_arg], "group")) {
1334 struct group *group;
1335
1336 group = getgrnam(args[cur_arg + 1]);
1337 if (!group) {
1338 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1339 file, linenum, args[0], args[cur_arg + 1 ]);
1340 err_code |= ERR_ALERT | ERR_FATAL;
1341 goto out;
1342 }
1343
1344 global.unix_bind.ux.gid = group->gr_gid;
1345 cur_arg += 2;
1346 continue;
1347 }
1348
Willy Tarreaub48f9582011-09-05 01:17:06 +02001349 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001350 file, linenum, args[0]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
1354 }
William Lallemand0f99e342011-10-12 17:50:54 +02001355 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1356 /* delete previous herited or defined syslog servers */
1357 struct logsrv *back;
1358 struct logsrv *tmp;
1359
1360 if (*(args[1]) != 0) {
1361 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364 }
1365
1366 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1367 LIST_DEL(&tmp->list);
1368 free(tmp);
1369 }
1370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001372 struct sockaddr_storage *sk;
1373 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001374 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001375 int arg = 0;
1376 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001377
William Lallemand1a748ae2015-05-19 16:37:23 +02001378 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1379 goto out;
1380
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 if (*(args[1]) == 0 || *(args[2]) == 0) {
1382 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\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 }
William Lallemand0f99e342011-10-12 17:50:54 +02001386
Vincent Bernat02779b62016-04-03 13:48:43 +02001387 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001388
Willy Tarreau18324f52014-06-27 18:10:07 +02001389 /* just after the address, a length may be specified */
1390 if (strcmp(args[arg+2], "len") == 0) {
1391 len = atoi(args[arg+3]);
1392 if (len < 80 || len > 65535) {
1393 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1394 file, linenum, args[arg+3]);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
1397 }
1398 logsrv->maxlen = len;
1399
1400 /* skip these two args */
1401 arg += 2;
1402 }
1403 else
1404 logsrv->maxlen = MAX_SYSLOG_LEN;
1405
Christopher Faulet084aa962017-08-29 16:54:41 +02001406 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001407 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001408
Dragan Dosen1322d092015-09-22 16:05:32 +02001409 /* after the length, a format may be specified */
1410 if (strcmp(args[arg+2], "format") == 0) {
1411 logsrv->format = get_log_format(args[arg+3]);
1412 if (logsrv->format < 0) {
1413 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1414 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001415 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001416 goto out;
1417 }
1418
1419 /* skip these two args */
1420 arg += 2;
1421 }
1422
David Carlier97880bb2016-04-08 10:35:26 +01001423 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1424 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001425 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001426 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001427
Willy Tarreau18324f52014-06-27 18:10:07 +02001428 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001429 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001430 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434
William Lallemand0f99e342011-10-12 17:50:54 +02001435 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001436 if (*(args[arg+3])) {
1437 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001438 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001439 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001440 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001441 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 }
1443 }
1444
William Lallemand0f99e342011-10-12 17:50:54 +02001445 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001446 if (*(args[arg+4])) {
1447 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001448 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001449 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001450 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001451 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001452 }
1453 }
1454
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001455 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001456 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001457 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001458 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001459 free(logsrv);
1460 goto out;
1461 }
1462 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001463
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001464 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001465 if (port1 != port2) {
1466 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1467 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001468 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001469 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001470 goto out;
1471 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001472
William Lallemand0f99e342011-10-12 17:50:54 +02001473 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001474 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001475 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
William Lallemand0f99e342011-10-12 17:50:54 +02001478 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001479 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001480 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1481 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001482
1483 if (global.log_send_hostname != NULL) {
1484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1485 err_code |= ERR_ALERT;
1486 goto out;
1487 }
1488
1489 if (*(args[1]))
1490 name = args[1];
1491 else
1492 name = hostname;
1493
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001494 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001495 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001496 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001497 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1498 if (global.server_state_base != NULL) {
1499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1500 err_code |= ERR_ALERT;
1501 goto out;
1502 }
1503
1504 if (!*(args[1])) {
1505 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1506 err_code |= ERR_FATAL;
1507 goto out;
1508 }
1509
1510 global.server_state_base = strdup(args[1]);
1511 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001512 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1513 if (global.server_state_file != NULL) {
1514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1515 err_code |= ERR_ALERT;
1516 goto out;
1517 }
1518
1519 if (!*(args[1])) {
1520 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1521 err_code |= ERR_FATAL;
1522 goto out;
1523 }
1524
1525 global.server_state_file = strdup(args[1]);
1526 }
Kevinm48936af2010-12-22 16:08:21 +00001527 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001528 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1529 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001530 if (*(args[1]) == 0) {
1531 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
1534 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001535 chunk_destroy(&global.log_tag);
1536 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001537 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001538 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001539 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1540 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001541 if (global.spread_checks != 0) {
1542 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001543 err_code |= ERR_ALERT;
1544 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001545 }
1546 if (*(args[1]) == 0) {
1547 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001550 }
1551 global.spread_checks = atol(args[1]);
1552 if (global.spread_checks < 0 || global.spread_checks > 50) {
1553 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001554 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001557 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1558 const char *err;
1559 unsigned int val;
1560
William Lallemand1a748ae2015-05-19 16:37:23 +02001561 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1562 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001563 if (*(args[1]) == 0) {
1564 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1565 err_code |= ERR_ALERT | ERR_FATAL;
1566 goto out;
1567 }
1568
1569 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1570 if (err) {
1571 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1572 err_code |= ERR_ALERT | ERR_FATAL;
1573 }
1574 global.max_spread_checks = val;
1575 if (global.max_spread_checks < 0) {
1576 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1577 err_code |= ERR_ALERT | ERR_FATAL;
1578 }
1579 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001580 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1581#ifdef USE_CPU_AFFINITY
1582 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001583 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001584 unsigned long cpus = 0;
1585
1586 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001587 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001588 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001589 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001590 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001591 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001592 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001593 proc = atol(args[1]);
1594 if (proc >= 1 && proc <= LONGBITS)
1595 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001596 }
1597
1598 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001599 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",
1600 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001601 err_code |= ERR_ALERT | ERR_FATAL;
1602 goto out;
1603 }
1604
1605 cur_arg = 2;
1606 while (*args[cur_arg]) {
1607 unsigned int low, high;
1608
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001609 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001610 char *dash = strchr(args[cur_arg], '-');
1611
1612 low = high = str2uic(args[cur_arg]);
1613 if (dash)
1614 high = str2uic(dash + 1);
1615
1616 if (high < low) {
1617 unsigned int swap = low;
1618 low = high;
1619 high = swap;
1620 }
1621
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001622 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001623 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001624 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
1627 }
1628
1629 while (low <= high)
1630 cpus |= 1UL << low++;
1631 }
1632 else {
1633 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1634 file, linenum, args[0], args[cur_arg]);
1635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
1637 }
1638 cur_arg++;
1639 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001640 for (i = 0; i < LONGBITS; i++)
1641 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001642 global.cpu_map[i] = cpus;
1643#else
1644 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
1647#endif
1648 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001649 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1650 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1651 goto out;
1652
1653 if (*(args[2]) == 0) {
1654 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1655 err_code |= ERR_ALERT | ERR_FATAL;
1656 goto out;
1657 }
1658
1659 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1660 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1661 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
1664 }
1665 }
1666 else if (!strcmp(args[0], "unsetenv")) {
1667 int arg;
1668
1669 if (*(args[1]) == 0) {
1670 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
1673 }
1674
1675 for (arg = 1; *args[arg]; arg++) {
1676 if (unsetenv(args[arg]) != 0) {
1677 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
1680 }
1681 }
1682 }
1683 else if (!strcmp(args[0], "resetenv")) {
1684 extern char **environ;
1685 char **env = environ;
1686
1687 /* args contain variable names to keep, one per argument */
1688 while (*env) {
1689 int arg;
1690
1691 /* look for current variable in among all those we want to keep */
1692 for (arg = 1; *args[arg]; arg++) {
1693 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1694 (*env)[strlen(args[arg])] == '=')
1695 break;
1696 }
1697
1698 /* delete this variable */
1699 if (!*args[arg]) {
1700 char *delim = strchr(*env, '=');
1701
1702 if (!delim || delim - *env >= trash.size) {
1703 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707
1708 memcpy(trash.str, *env, delim - *env);
1709 trash.str[delim - *env] = 0;
1710
1711 if (unsetenv(trash.str) != 0) {
1712 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1713 err_code |= ERR_ALERT | ERR_FATAL;
1714 goto out;
1715 }
1716 }
1717 else
1718 env++;
1719 }
1720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001722 struct cfg_kw_list *kwl;
1723 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001724 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001725
1726 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1727 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1728 if (kwl->kw[index].section != CFG_GLOBAL)
1729 continue;
1730 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001731 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001732 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001733 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001735 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001736 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001737 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001738 err_code |= ERR_WARN;
1739 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001740 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001741 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001742 }
1743 }
1744 }
1745
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001747 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001749
Willy Tarreau058e9072009-07-20 09:30:05 +02001750 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001751 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001752 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753}
1754
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001755void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001757 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 defproxy.mode = PR_MODE_TCP;
1759 defproxy.state = PR_STNEW;
1760 defproxy.maxconn = cfg_maxpconn;
1761 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001762 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001763 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001764
Simon Horman66183002013-02-23 10:16:43 +09001765 defproxy.defsrv.check.inter = DEF_CHKINTR;
1766 defproxy.defsrv.check.fastinter = 0;
1767 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001768 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1769 defproxy.defsrv.agent.fastinter = 0;
1770 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001771 defproxy.defsrv.check.rise = DEF_RISETIME;
1772 defproxy.defsrv.check.fall = DEF_FALLTIME;
1773 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1774 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001775 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001776 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001777 defproxy.defsrv.maxqueue = 0;
1778 defproxy.defsrv.minconn = 0;
1779 defproxy.defsrv.maxconn = 0;
1780 defproxy.defsrv.slowstart = 0;
1781 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1782 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1783 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001784
1785 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001786 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787}
1788
Willy Tarreauade5ec42010-01-28 19:33:49 +01001789
Willy Tarreau63af98d2014-05-18 08:11:41 +02001790/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1791 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1792 * ERR_FATAL in case of error.
1793 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001794static int create_cond_regex_rule(const char *file, int line,
1795 struct proxy *px, int dir, int action, int flags,
1796 const char *cmd, const char *reg, const char *repl,
1797 const char **cond_start)
1798{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001799 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001800 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001801 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001802 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001803 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001804 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001805 int cs;
1806 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001807
1808 if (px == &defproxy) {
1809 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001810 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001811 goto err;
1812 }
1813
1814 if (*reg == 0) {
1815 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001816 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001817 goto err;
1818 }
1819
Christopher Faulet898566e2016-10-26 11:06:28 +02001820 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001821 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001822
Willy Tarreau5321c422010-01-28 20:35:13 +01001823 if (cond_start &&
1824 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02001825 if ((cond = build_acl_cond(file, line, &px->acl, px, cond_start, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001826 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1827 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001828 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001829 goto err;
1830 }
1831 }
1832 else if (cond_start && **cond_start) {
1833 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1834 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001835 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001836 goto err;
1837 }
1838
Willy Tarreau63af98d2014-05-18 08:11:41 +02001839 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001840 (dir == SMP_OPT_DIR_REQ) ?
1841 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1842 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1843 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001844
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001845 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001846 if (!preg) {
1847 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001848 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001849 goto err;
1850 }
1851
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001852 cs = !(flags & REG_ICASE);
1853 cap = !(flags & REG_NOSUB);
1854 error = NULL;
1855 if (!regex_comp(reg, preg, cs, cap, &error)) {
1856 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1857 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001858 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001859 goto err;
1860 }
1861
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001862 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001863 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001864 if (repl && err) {
1865 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1866 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001867 ret_code |= ERR_ALERT | ERR_FATAL;
1868 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001869 }
1870
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001871 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001872 ret_code |= ERR_WARN;
1873
1874 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001875
Willy Tarreau63af98d2014-05-18 08:11:41 +02001876 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001877 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001878 err:
1879 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001880 free(errmsg);
1881 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001882}
1883
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884/*
William Lallemand51097192015-04-14 16:35:22 +02001885 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001886 * Returns the error code, 0 if OK, or any combination of :
1887 * - ERR_ABORT: must abort ASAP
1888 * - ERR_FATAL: we can continue parsing but not start the service
1889 * - ERR_WARN: a warning has been emitted
1890 * - ERR_ALERT: an alert has been emitted
1891 * Only the two first ones can stop processing, the two others are just
1892 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001894int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1895{
1896 static struct peers *curpeers = NULL;
1897 struct peer *newpeer = NULL;
1898 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001899 struct bind_conf *bind_conf;
1900 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001901 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001902 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001903
1904 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001905 if (!*args[1]) {
1906 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001907 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001908 goto out;
1909 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001910
William Lallemand6e62fb62015-04-28 16:55:23 +02001911 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1912 goto out;
1913
Emeric Brun32da3c42010-09-23 18:39:19 +02001914 err = invalid_char(args[1]);
1915 if (err) {
1916 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1917 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001918 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001919 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001920 }
1921
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001922 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001923 /*
1924 * If there are two proxies with the same name only following
1925 * combinations are allowed:
1926 */
1927 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001928 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 +02001929 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001930 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001931 }
1932 }
1933
Vincent Bernat02779b62016-04-03 13:48:43 +02001934 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001935 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1936 err_code |= ERR_ALERT | ERR_ABORT;
1937 goto out;
1938 }
1939
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001940 curpeers->next = cfg_peers;
1941 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001942 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001943 curpeers->conf.line = linenum;
1944 curpeers->last_change = now.tv_sec;
1945 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001946 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001947 }
1948 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001949 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001950 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001951 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001952
1953 if (!*args[2]) {
1954 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1955 file, linenum, args[0]);
1956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
1958 }
1959
1960 err = invalid_char(args[1]);
1961 if (err) {
1962 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1963 file, linenum, *err, args[1]);
1964 err_code |= ERR_ALERT | ERR_FATAL;
1965 goto out;
1966 }
1967
Vincent Bernat02779b62016-04-03 13:48:43 +02001968 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001969 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1970 err_code |= ERR_ALERT | ERR_ABORT;
1971 goto out;
1972 }
1973
1974 /* the peers are linked backwards first */
1975 curpeers->count++;
1976 newpeer->next = curpeers->remote;
1977 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001978 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001979 newpeer->conf.line = linenum;
1980
1981 newpeer->last_change = now.tv_sec;
1982 newpeer->id = strdup(args[1]);
1983
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001984 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001985 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001986 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001987 err_code |= ERR_ALERT | ERR_FATAL;
1988 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001989 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001990
1991 proto = protocol_by_family(sk->ss_family);
1992 if (!proto || !proto->connect) {
1993 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1994 file, linenum, args[0], args[1]);
1995 err_code |= ERR_ALERT | ERR_FATAL;
1996 goto out;
1997 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001998
1999 if (port1 != port2) {
2000 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2001 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
2004 }
2005
Willy Tarreau2aa38802013-02-20 19:20:59 +01002006 if (!port1) {
2007 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2008 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
2011 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002012
Emeric Brun32da3c42010-09-23 18:39:19 +02002013 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002014 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002015 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002016 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002017
Emeric Brun32da3c42010-09-23 18:39:19 +02002018 if (strcmp(newpeer->id, localpeer) == 0) {
2019 /* Current is local peer, it define a frontend */
2020 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002021 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002022
2023 if (!curpeers->peers_fe) {
2024 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2025 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2026 err_code |= ERR_ALERT | ERR_ABORT;
2027 goto out;
2028 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002029
Willy Tarreau237250c2011-07-29 01:49:03 +02002030 init_new_proxy(curpeers->peers_fe);
2031 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002032 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002033 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2034 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002035 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002036
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002037 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002038
Willy Tarreau902636f2013-03-10 19:44:48 +01002039 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2040 if (errmsg && *errmsg) {
2041 indent_msg(&errmsg, 2);
2042 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002043 }
2044 else
2045 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2046 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002047 err_code |= ERR_FATAL;
2048 goto out;
2049 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002050
2051 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002052 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002053 l->maxconn = curpeers->peers_fe->maxconn;
2054 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002055 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002056 l->analysers |= curpeers->peers_fe->fe_req_ana;
2057 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002058 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2059 global.maxsock += l->maxconn;
2060 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002061 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002062 else {
2063 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2064 file, linenum, args[0], args[1],
2065 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2066 err_code |= ERR_FATAL;
2067 goto out;
2068 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 }
2070 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002071 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2072 curpeers->state = PR_STSTOPPED;
2073 }
2074 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2075 curpeers->state = PR_STNEW;
2076 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002077 else if (*args[0] != 0) {
2078 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
2081 }
2082
2083out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002084 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002085 return err_code;
2086}
2087
Baptiste Assmann325137d2015-04-13 23:40:55 +02002088/*
2089 * Parse a <resolvers> section.
2090 * Returns the error code, 0 if OK, or any combination of :
2091 * - ERR_ABORT: must abort ASAP
2092 * - ERR_FATAL: we can continue parsing but not start the service
2093 * - ERR_WARN: a warning has been emitted
2094 * - ERR_ALERT: an alert has been emitted
2095 * Only the two first ones can stop processing, the two others are just
2096 * indicators.
2097 */
2098int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2099{
2100 static struct dns_resolvers *curr_resolvers = NULL;
2101 struct dns_nameserver *newnameserver = NULL;
2102 const char *err;
2103 int err_code = 0;
2104 char *errmsg = NULL;
2105
2106 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2107 if (!*args[1]) {
2108 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2109 err_code |= ERR_ALERT | ERR_ABORT;
2110 goto out;
2111 }
2112
2113 err = invalid_char(args[1]);
2114 if (err) {
2115 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2116 file, linenum, *err, args[0], args[1]);
2117 err_code |= ERR_ALERT | ERR_ABORT;
2118 goto out;
2119 }
2120
2121 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2122 /* Error if two resolvers owns the same name */
2123 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2124 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2125 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2126 err_code |= ERR_ALERT | ERR_ABORT;
2127 }
2128 }
2129
Vincent Bernat02779b62016-04-03 13:48:43 +02002130 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2132 err_code |= ERR_ALERT | ERR_ABORT;
2133 goto out;
2134 }
2135
2136 /* default values */
2137 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2138 curr_resolvers->conf.file = strdup(file);
2139 curr_resolvers->conf.line = linenum;
2140 curr_resolvers->id = strdup(args[1]);
2141 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002142 /* default maximum response size */
2143 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002144 /* default hold period for nx, other, refuse and timeout is 30s */
2145 curr_resolvers->hold.nx = 30000;
2146 curr_resolvers->hold.other = 30000;
2147 curr_resolvers->hold.refused = 30000;
2148 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002149 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002150 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002151 curr_resolvers->hold.valid = 10000;
2152 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002153 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002154 /* default resolution pool size */
2155 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002156 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002157 LIST_INIT(&curr_resolvers->resolution.curr);
2158 LIST_INIT(&curr_resolvers->resolution.wait);
2159 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002160 }
2161 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2162 struct sockaddr_storage *sk;
2163 int port1, port2;
2164 struct protocol *proto;
2165
2166 if (!*args[2]) {
2167 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2168 file, linenum, args[0]);
2169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
2171 }
2172
2173 err = invalid_char(args[1]);
2174 if (err) {
2175 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2176 file, linenum, *err, args[1]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
Baptiste Assmanna315c552015-11-02 22:55:49 +01002181 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2182 /* Error if two resolvers owns the same name */
2183 if (strcmp(newnameserver->id, args[1]) == 0) {
2184 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2185 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 }
2188 }
2189
Vincent Bernat02779b62016-04-03 13:48:43 +02002190 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2192 err_code |= ERR_ALERT | ERR_ABORT;
2193 goto out;
2194 }
2195
2196 /* the nameservers are linked backward first */
2197 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2198 curr_resolvers->count_nameservers++;
2199 newnameserver->resolvers = curr_resolvers;
2200 newnameserver->conf.file = strdup(file);
2201 newnameserver->conf.line = linenum;
2202 newnameserver->id = strdup(args[1]);
2203
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002204 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002205 if (!sk) {
2206 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210
2211 proto = protocol_by_family(sk->ss_family);
2212 if (!proto || !proto->connect) {
2213 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2214 file, linenum, args[0], args[1]);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
2217 }
2218
2219 if (port1 != port2) {
2220 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2221 file, linenum, args[0], args[1], args[2]);
2222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
2224 }
2225
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002226 if (!port1 && !port2) {
2227 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2228 file, linenum, args[0], args[1]);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
2232
Baptiste Assmann325137d2015-04-13 23:40:55 +02002233 newnameserver->addr = *sk;
2234 }
2235 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2236 const char *res;
2237 unsigned int time;
2238
2239 if (!*args[2]) {
2240 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2241 file, linenum, args[0]);
2242 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
2246 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2247 if (res) {
2248 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2249 file, linenum, *res, args[0]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002253 if (strcmp(args[1], "nx") == 0)
2254 curr_resolvers->hold.nx = time;
2255 else if (strcmp(args[1], "other") == 0)
2256 curr_resolvers->hold.other = time;
2257 else if (strcmp(args[1], "refused") == 0)
2258 curr_resolvers->hold.refused = time;
2259 else if (strcmp(args[1], "timeout") == 0)
2260 curr_resolvers->hold.timeout = time;
2261 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002262 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002263 else if (strcmp(args[1], "obsolete") == 0)
2264 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002265 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002266 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002267 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
2270 }
2271
2272 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002273 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002274 int i = 0;
2275
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002276 if (!*args[1]) {
2277 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2278 file, linenum, args[0]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002282
2283 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002284 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2285 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2286 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
2289 }
2290
2291 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002292 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002293 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2294 if (!*args[1]) {
2295 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2296 file, linenum, args[0]);
2297 err_code |= ERR_ALERT | ERR_FATAL;
2298 goto out;
2299 }
2300 curr_resolvers->resolution_pool_size = atoi(args[1]);
2301 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002302 else if (strcmp(args[0], "resolve_retries") == 0) {
2303 if (!*args[1]) {
2304 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2305 file, linenum, args[0]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309 curr_resolvers->resolve_retries = atoi(args[1]);
2310 }
2311 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002312 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002313 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2314 file, linenum, args[0]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002318 else if (strcmp(args[1], "retry") == 0) {
2319 const char *res;
2320 unsigned int timeout_retry;
2321
2322 if (!*args[2]) {
2323 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2324 file, linenum, args[0], args[1]);
2325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
2327 }
2328 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2329 if (res) {
2330 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2331 file, linenum, *res, args[0], args[1]);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335 curr_resolvers->timeout.retry = timeout_retry;
2336 }
2337 else {
2338 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2339 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002343 } /* neither "nameserver" nor "resolvers" */
2344 else if (*args[0] != 0) {
2345 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349
2350 out:
2351 free(errmsg);
2352 return err_code;
2353}
Simon Horman0d16a402015-01-30 11:22:58 +09002354
2355/*
William Lallemand51097192015-04-14 16:35:22 +02002356 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002357 * Returns the error code, 0 if OK, or any combination of :
2358 * - ERR_ABORT: must abort ASAP
2359 * - ERR_FATAL: we can continue parsing but not start the service
2360 * - ERR_WARN: a warning has been emitted
2361 * - ERR_ALERT: an alert has been emitted
2362 * Only the two first ones can stop processing, the two others are just
2363 * indicators.
2364 */
2365int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2366{
2367 static struct mailers *curmailers = NULL;
2368 struct mailer *newmailer = NULL;
2369 const char *err;
2370 int err_code = 0;
2371 char *errmsg = NULL;
2372
2373 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2374 if (!*args[1]) {
2375 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2376 err_code |= ERR_ALERT | ERR_ABORT;
2377 goto out;
2378 }
2379
2380 err = invalid_char(args[1]);
2381 if (err) {
2382 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2383 file, linenum, *err, args[0], args[1]);
2384 err_code |= ERR_ALERT | ERR_ABORT;
2385 goto out;
2386 }
2387
2388 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2389 /*
2390 * If there are two proxies with the same name only following
2391 * combinations are allowed:
2392 */
2393 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002394 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 +09002395 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002397 }
2398 }
2399
Vincent Bernat02779b62016-04-03 13:48:43 +02002400 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002401 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2402 err_code |= ERR_ALERT | ERR_ABORT;
2403 goto out;
2404 }
2405
2406 curmailers->next = mailers;
2407 mailers = curmailers;
2408 curmailers->conf.file = strdup(file);
2409 curmailers->conf.line = linenum;
2410 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002411 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2412 * But need enough time so that timeouts don't occur
2413 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002414 }
2415 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2416 struct sockaddr_storage *sk;
2417 int port1, port2;
2418 struct protocol *proto;
2419
2420 if (!*args[2]) {
2421 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2422 file, linenum, args[0]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 err = invalid_char(args[1]);
2428 if (err) {
2429 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2430 file, linenum, *err, args[1]);
2431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
2433 }
2434
Vincent Bernat02779b62016-04-03 13:48:43 +02002435 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002436 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2437 err_code |= ERR_ALERT | ERR_ABORT;
2438 goto out;
2439 }
2440
2441 /* the mailers are linked backwards first */
2442 curmailers->count++;
2443 newmailer->next = curmailers->mailer_list;
2444 curmailers->mailer_list = newmailer;
2445 newmailer->mailers = curmailers;
2446 newmailer->conf.file = strdup(file);
2447 newmailer->conf.line = linenum;
2448
2449 newmailer->id = strdup(args[1]);
2450
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002451 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002452 if (!sk) {
2453 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
2458 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002459 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2460 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002461 file, linenum, args[0], args[1]);
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465
2466 if (port1 != port2) {
2467 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2468 file, linenum, args[0], args[1], args[2]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472
2473 if (!port1) {
2474 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2475 file, linenum, args[0], args[1], args[2]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479
2480 newmailer->addr = *sk;
2481 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002482 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002483 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002484 }
2485 else if (strcmp(args[0], "timeout") == 0) {
2486 if (!*args[1]) {
2487 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2488 file, linenum, args[0]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492 else if (strcmp(args[1], "mail") == 0) {
2493 const char *res;
2494 unsigned int timeout_mail;
2495 if (!*args[2]) {
2496 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2497 file, linenum, args[0], args[1]);
2498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
2501 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2502 if (res) {
2503 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2504 file, linenum, *res, args[0]);
2505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
2508 if (timeout_mail <= 0) {
2509 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
2512 }
2513 curmailers->timeout.mail = timeout_mail;
2514 } else {
2515 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2516 file, linenum, args[0], args[1]);
2517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
2519 }
2520 }
Simon Horman0d16a402015-01-30 11:22:58 +09002521 else if (*args[0] != 0) {
2522 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
2525 }
2526
2527out:
2528 free(errmsg);
2529 return err_code;
2530}
2531
Simon Horman9dc49962015-01-30 11:22:59 +09002532static void free_email_alert(struct proxy *p)
2533{
2534 free(p->email_alert.mailers.name);
2535 p->email_alert.mailers.name = NULL;
2536 free(p->email_alert.from);
2537 p->email_alert.from = NULL;
2538 free(p->email_alert.to);
2539 p->email_alert.to = NULL;
2540 free(p->email_alert.myhostname);
2541 p->email_alert.myhostname = NULL;
2542}
2543
Willy Tarreau3842f002009-06-14 11:39:52 +02002544int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545{
2546 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002547 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002548 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002549 int rc;
2550 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002551 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002552 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002553 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002554 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002555 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 if (!strcmp(args[0], "listen"))
2558 rc = PR_CAP_LISTEN;
2559 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002560 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002561 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002562 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563 else
2564 rc = PR_CAP_NONE;
2565
2566 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 if (!*args[1]) {
2568 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002569 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_ABORT;
2572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002574
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002575 err = invalid_char(args[1]);
2576 if (err) {
2577 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2578 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002580 }
2581
Willy Tarreau8f50b682015-05-26 11:45:02 +02002582 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2583 if (curproxy) {
2584 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2585 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2586 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002588 }
2589
Vincent Bernat02779b62016-04-03 13:48:43 +02002590 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_ABORT;
2593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002595
Willy Tarreau97cb7802010-01-03 20:23:58 +01002596 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 curproxy->next = proxy;
2598 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002599 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2600 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002601 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002603 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002604 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605
William Lallemand6e62fb62015-04-28 16:55:23 +02002606 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2607 if (curproxy->cap & PR_CAP_FE)
2608 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 }
2611
2612 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002613 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002614 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002615
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002618 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002619 curproxy->no_options = defproxy.no_options;
2620 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002621 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002622 curproxy->except_net = defproxy.except_net;
2623 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002624 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002625 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002627 if (defproxy.fwdfor_hdr_len) {
2628 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2629 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2630 }
2631
Willy Tarreaub86db342009-11-30 11:50:16 +01002632 if (defproxy.orgto_hdr_len) {
2633 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2634 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2635 }
2636
Mark Lamourinec2247f02012-01-04 13:02:01 -05002637 if (defproxy.server_id_hdr_len) {
2638 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2639 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2640 }
2641
Willy Tarreau977b8e42006-12-29 14:19:17 +01002642 if (curproxy->cap & PR_CAP_FE) {
2643 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002644 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002645 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002646
2647 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002648 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2649 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650
2651 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653
Willy Tarreau977b8e42006-12-29 14:19:17 +01002654 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002655 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002656 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002657 curproxy->fullconn = defproxy.fullconn;
2658 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002659 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002660 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002662 if (defproxy.check_req) {
2663 curproxy->check_req = calloc(1, defproxy.check_len);
2664 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2665 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002666 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002668 if (defproxy.expect_str) {
2669 curproxy->expect_str = strdup(defproxy.expect_str);
2670 if (defproxy.expect_regex) {
2671 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002672 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2673 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002674 }
2675 }
2676
Willy Tarreau67402132012-05-31 20:40:20 +02002677 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678 if (defproxy.cookie_name)
2679 curproxy->cookie_name = strdup(defproxy.cookie_name);
2680 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002681
2682 if (defproxy.dyncookie_key)
2683 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002684 if (defproxy.cookie_domain)
2685 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002686
Willy Tarreau31936852010-10-06 16:59:56 +02002687 if (defproxy.cookie_maxidle)
2688 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2689
2690 if (defproxy.cookie_maxlife)
2691 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2692
Emeric Brun647caf12009-06-30 17:57:00 +02002693 if (defproxy.rdp_cookie_name)
2694 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2695 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2696
Willy Tarreau01732802007-11-01 22:48:15 +01002697 if (defproxy.url_param_name)
2698 curproxy->url_param_name = strdup(defproxy.url_param_name);
2699 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002700
Benoitaffb4812009-03-25 13:02:10 +01002701 if (defproxy.hh_name)
2702 curproxy->hh_name = strdup(defproxy.hh_name);
2703 curproxy->hh_len = defproxy.hh_len;
2704 curproxy->hh_match_domain = defproxy.hh_match_domain;
2705
Willy Tarreauef9a3602012-12-08 22:29:20 +01002706 if (defproxy.conn_src.iface_name)
2707 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2708 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002709 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002710#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002711 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002712#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002713 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002716 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 if (defproxy.capture_name)
2718 curproxy->capture_name = strdup(defproxy.capture_name);
2719 curproxy->capture_namelen = defproxy.capture_namelen;
2720 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722
Willy Tarreau977b8e42006-12-29 14:19:17 +01002723 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002724 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002725 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002726 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002727 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002728 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729 curproxy->mon_net = defproxy.mon_net;
2730 curproxy->mon_mask = defproxy.mon_mask;
2731 if (defproxy.monitor_uri)
2732 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2733 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002734 if (defproxy.defbe.name)
2735 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002736
2737 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002738 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2739 if (curproxy->conf.logformat_string &&
2740 curproxy->conf.logformat_string != default_http_log_format &&
2741 curproxy->conf.logformat_string != default_tcp_log_format &&
2742 curproxy->conf.logformat_string != clf_http_log_format)
2743 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2744
2745 if (defproxy.conf.lfs_file) {
2746 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2747 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2748 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002749
2750 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2751 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2752 if (curproxy->conf.logformat_sd_string &&
2753 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2754 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2755
2756 if (defproxy.conf.lfsd_file) {
2757 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2758 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2759 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002760 }
2761
2762 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002763 curproxy->timeout.connect = defproxy.timeout.connect;
2764 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002765 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002766 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002767 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002768 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002769 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002770 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002771 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002772 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002773 }
2774
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002776 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002777
2778 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002779 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002780 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002781 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002782 LIST_INIT(&node->list);
2783 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2784 }
2785
Willy Tarreau62a61232013-04-12 18:13:46 +02002786 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2787 if (curproxy->conf.uniqueid_format_string)
2788 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2789
Dragan Dosen43885c72015-10-01 13:18:13 +02002790 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002791
Willy Tarreau62a61232013-04-12 18:13:46 +02002792 if (defproxy.conf.uif_file) {
2793 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2794 curproxy->conf.uif_line = defproxy.conf.uif_line;
2795 }
William Lallemanda73203e2012-03-12 12:48:57 +01002796
2797 /* copy default header unique id */
2798 if (defproxy.header_unique_id)
2799 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2800
William Lallemand82fe75c2012-10-23 10:25:10 +02002801 /* default compression options */
2802 if (defproxy.comp != NULL) {
2803 curproxy->comp = calloc(1, sizeof(struct comp));
2804 curproxy->comp->algos = defproxy.comp->algos;
2805 curproxy->comp->types = defproxy.comp->types;
2806 }
2807
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002809 curproxy->conf.used_listener_id = EB_ROOT;
2810 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002811
Simon Horman98637e52014-06-20 12:30:16 +09002812 if (defproxy.check_path)
2813 curproxy->check_path = strdup(defproxy.check_path);
2814 if (defproxy.check_command)
2815 curproxy->check_command = strdup(defproxy.check_command);
2816
Simon Horman9dc49962015-01-30 11:22:59 +09002817 if (defproxy.email_alert.mailers.name)
2818 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2819 if (defproxy.email_alert.from)
2820 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2821 if (defproxy.email_alert.to)
2822 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2823 if (defproxy.email_alert.myhostname)
2824 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002825 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002826 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002827
Willy Tarreau93893792009-07-23 13:19:11 +02002828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 }
2830 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2831 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002832 /* FIXME-20070101: we should do this too at the end of the
2833 * config parsing to free all default values.
2834 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002835 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2836 err_code |= ERR_ABORT;
2837 goto out;
2838 }
2839
Willy Tarreaua534fea2008-08-03 12:19:50 +02002840 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002841 free(defproxy.check_command);
2842 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002843 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002844 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002845 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002846 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002847 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002848 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002849 free(defproxy.capture_name);
2850 free(defproxy.monitor_uri);
2851 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002852 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002853 free(defproxy.fwdfor_hdr_name);
2854 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002855 free(defproxy.orgto_hdr_name);
2856 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002857 free(defproxy.server_id_hdr_name);
2858 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002859 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002860 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002861 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002862 free(defproxy.expect_regex);
2863 defproxy.expect_regex = NULL;
2864 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002865
Willy Tarreau62a61232013-04-12 18:13:46 +02002866 if (defproxy.conf.logformat_string != default_http_log_format &&
2867 defproxy.conf.logformat_string != default_tcp_log_format &&
2868 defproxy.conf.logformat_string != clf_http_log_format)
2869 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002870
Willy Tarreau62a61232013-04-12 18:13:46 +02002871 free(defproxy.conf.uniqueid_format_string);
2872 free(defproxy.conf.lfs_file);
2873 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002874 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002875 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002876
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002877 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2878 free(defproxy.conf.logformat_sd_string);
2879 free(defproxy.conf.lfsd_file);
2880
Willy Tarreaua534fea2008-08-03 12:19:50 +02002881 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002882 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002883
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 /* we cannot free uri_auth because it might already be used */
2885 init_default_instance();
2886 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002887 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2888 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 }
2892 else if (curproxy == NULL) {
2893 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002897
2898 /* update the current file and line being parsed */
2899 curproxy->conf.args.file = curproxy->conf.file;
2900 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002901
2902 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002903 if (!strcmp(args[0], "server") ||
2904 !strcmp(args[0], "default-server") ||
2905 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002906 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2907 if (err_code & ERR_FATAL)
2908 goto out;
2909 }
2910 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002911 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002912 int cur_arg;
2913
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 if (curproxy == &defproxy) {
2915 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002919 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921
Willy Tarreau24709282013-03-10 21:32:12 +01002922 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002923 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002928
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002929 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002930
2931 /* use default settings for unix sockets */
2932 bind_conf->ux.uid = global.unix_bind.ux.uid;
2933 bind_conf->ux.gid = global.unix_bind.ux.gid;
2934 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002935
2936 /* NOTE: the following line might create several listeners if there
2937 * are comma-separated IPs or port ranges. So all further processing
2938 * will have to be applied to all listeners created after last_listen.
2939 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002940 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2941 if (errmsg && *errmsg) {
2942 indent_msg(&errmsg, 2);
2943 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002944 }
2945 else
2946 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2947 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002951
Willy Tarreau4348fad2012-09-20 16:48:07 +02002952 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2953 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002954 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002955 }
2956
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002957 cur_arg = 2;
2958 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002959 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002960 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002961 char *err;
2962
Willy Tarreau26982662012-09-12 23:17:10 +02002963 kw = bind_find_kw(args[cur_arg]);
2964 if (kw) {
2965 char *err = NULL;
2966 int code;
2967
2968 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002969 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2970 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002971 cur_arg += 1 + kw->skip ;
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975
Willy Tarreau4348fad2012-09-20 16:48:07 +02002976 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002977 err_code |= code;
2978
2979 if (code) {
2980 if (err && *err) {
2981 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002982 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002983 }
2984 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002985 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2986 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002987 if (code & ERR_FATAL) {
2988 free(err);
2989 cur_arg += 1 + kw->skip;
2990 goto out;
2991 }
2992 }
2993 free(err);
2994 cur_arg += 1 + kw->skip;
2995 continue;
2996 }
2997
Willy Tarreau8638f482012-09-18 18:01:17 +02002998 err = NULL;
2999 if (!bind_dumped) {
3000 bind_dump_kws(&err);
3001 indent_msg(&err, 4);
3002 bind_dumped = 1;
3003 }
3004
3005 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3006 file, linenum, args[0], args[1], args[cur_arg],
3007 err ? " Registered keywords :" : "", err ? err : "");
3008 free(err);
3009
Willy Tarreau93893792009-07-23 13:19:11 +02003010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003012 }
Willy Tarreau93893792009-07-23 13:19:11 +02003013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
3015 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003016 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003022 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003024
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 /* flush useless bits */
3026 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003029 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003030 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003032
William Lallemanddf1425a2015-04-28 20:17:49 +02003033 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3034 goto out;
3035
Willy Tarreau1c47f852006-07-09 08:22:27 +02003036 if (!*args[1]) {
3037 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003041 }
3042
Willy Tarreaua534fea2008-08-03 12:19:50 +02003043 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003044 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003045 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003046 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003047 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3048
Willy Tarreau93893792009-07-23 13:19:11 +02003049 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003052 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3053 goto out;
3054
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3056 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3057 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3058 else {
3059 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 }
3063 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003064 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003065 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003066
3067 if (curproxy == &defproxy) {
3068 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003072 }
3073
William Lallemanddf1425a2015-04-28 20:17:49 +02003074 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3075 goto out;
3076
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003077 if (!*args[1]) {
3078 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003082 }
3083
3084 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003085 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003086 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003087
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003088 if (curproxy->uuid <= 0) {
3089 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003090 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003093 }
3094
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003095 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3096 if (node) {
3097 struct proxy *target = container_of(node, struct proxy, conf.id);
3098 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3099 file, linenum, proxy_type_str(curproxy), curproxy->id,
3100 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003105 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003106 else if (!strcmp(args[0], "description")) {
3107 int i, len=0;
3108 char *d;
3109
Cyril Bonté99ed3272010-01-24 23:29:44 +01003110 if (curproxy == &defproxy) {
3111 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3112 file, linenum, args[0]);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003117 if (!*args[1]) {
3118 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3119 file, linenum, args[0]);
3120 return -1;
3121 }
3122
Willy Tarreau348acfe2014-04-14 15:00:39 +02003123 for (i = 1; *args[i]; i++)
3124 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003125
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003126 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003127 curproxy->desc = d;
3128
Willy Tarreau348acfe2014-04-14 15:00:39 +02003129 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3130 for (i = 2; *args[i]; i++)
3131 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003132
3133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003135 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 curproxy->state = PR_STSTOPPED;
3138 }
3139 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003140 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 curproxy->state = PR_STNEW;
3143 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003144 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3145 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003146 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003147
3148 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003149 unsigned int low, high;
3150
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003151 if (strcmp(args[cur_arg], "all") == 0) {
3152 set = 0;
3153 break;
3154 }
3155 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003156 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003157 }
3158 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003159 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003160 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003161 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003162 char *dash = strchr(args[cur_arg], '-');
3163
3164 low = high = str2uic(args[cur_arg]);
3165 if (dash)
3166 high = str2uic(dash + 1);
3167
3168 if (high < low) {
3169 unsigned int swap = low;
3170 low = high;
3171 high = swap;
3172 }
3173
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003174 if (low < 1 || high > LONGBITS) {
3175 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3176 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003179 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003180 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003181 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003182 }
3183 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003184 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3185 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003188 }
3189 cur_arg++;
3190 }
3191 curproxy->bind_proc = set;
3192 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003193 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003194 if (curproxy == &defproxy) {
3195 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003198 }
3199
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003200 err = invalid_char(args[1]);
3201 if (err) {
3202 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3203 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003205 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003206 }
3207
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003208 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003209 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3210 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003213 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003214 }
3215 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3216
3217 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3218 err_code |= ERR_WARN;
3219
3220 if (*(args[1]) == 0) {
3221 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3222 file, linenum, args[0]);
3223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
3226 free(curproxy->dyncookie_key);
3227 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3230 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231
Willy Tarreau977b8e42006-12-29 14:19:17 +01003232 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003234
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 if (*(args[1]) == 0) {
3236 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3237 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003241
Willy Tarreau67402132012-05-31 20:40:20 +02003242 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003243 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003244 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003245 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 curproxy->cookie_name = strdup(args[1]);
3247 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003248
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 cur_arg = 2;
3250 while (*(args[cur_arg])) {
3251 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003252 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 }
3254 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003255 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 }
3257 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003258 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 }
3260 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003261 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 }
3263 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003264 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003266 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003267 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003270 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003272 else if (!strcmp(args[cur_arg], "httponly")) {
3273 curproxy->ck_opts |= PR_CK_HTTPONLY;
3274 }
3275 else if (!strcmp(args[cur_arg], "secure")) {
3276 curproxy->ck_opts |= PR_CK_SECURE;
3277 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003278 else if (!strcmp(args[cur_arg], "domain")) {
3279 if (!*args[cur_arg + 1]) {
3280 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3281 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003284 }
3285
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003286 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003287 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003288 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3289 " dots nor does not start with a dot."
3290 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003291 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003292 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003293 }
3294
3295 err = invalid_domainchar(args[cur_arg + 1]);
3296 if (err) {
3297 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3298 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003301 }
3302
Willy Tarreau68a897b2009-12-03 23:28:34 +01003303 if (!curproxy->cookie_domain) {
3304 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3305 } else {
3306 /* one domain was already specified, add another one by
3307 * building the string which will be returned along with
3308 * the cookie.
3309 */
3310 char *new_ptr;
3311 int new_len = strlen(curproxy->cookie_domain) +
3312 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3313 new_ptr = malloc(new_len);
3314 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3315 free(curproxy->cookie_domain);
3316 curproxy->cookie_domain = new_ptr;
3317 }
Willy Tarreau31936852010-10-06 16:59:56 +02003318 cur_arg++;
3319 }
3320 else if (!strcmp(args[cur_arg], "maxidle")) {
3321 unsigned int maxidle;
3322 const char *res;
3323
3324 if (!*args[cur_arg + 1]) {
3325 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3326 file, linenum, args[cur_arg]);
3327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
3329 }
3330
3331 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3332 if (res) {
3333 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3334 file, linenum, *res, args[cur_arg]);
3335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
3337 }
3338 curproxy->cookie_maxidle = maxidle;
3339 cur_arg++;
3340 }
3341 else if (!strcmp(args[cur_arg], "maxlife")) {
3342 unsigned int maxlife;
3343 const char *res;
3344
3345 if (!*args[cur_arg + 1]) {
3346 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3347 file, linenum, args[cur_arg]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351
3352 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3353 if (res) {
3354 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3355 file, linenum, *res, args[cur_arg]);
3356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
3358 }
3359 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003360 cur_arg++;
3361 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003362 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003363
3364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3365 err_code |= ERR_WARN;
3366 curproxy->ck_opts |= PR_CK_DYNAMIC;
3367 }
3368
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003370 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
3375 cur_arg++;
3376 }
Willy Tarreau67402132012-05-31 20:40:20 +02003377 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3379 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 }
3382
Willy Tarreau67402132012-05-31 20:40:20 +02003383 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3385 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003388
Willy Tarreau67402132012-05-31 20:40:20 +02003389 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003390 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3391 file, linenum);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003395 else if (!strcmp(args[0], "email-alert")) {
3396 if (*(args[1]) == 0) {
3397 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3398 file, linenum, args[0]);
3399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
3401 }
3402
3403 if (!strcmp(args[1], "from")) {
3404 if (*(args[1]) == 0) {
3405 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3406 file, linenum, args[1]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
3410 free(curproxy->email_alert.from);
3411 curproxy->email_alert.from = strdup(args[2]);
3412 }
3413 else if (!strcmp(args[1], "mailers")) {
3414 if (*(args[1]) == 0) {
3415 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3416 file, linenum, args[1]);
3417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
3419 }
3420 free(curproxy->email_alert.mailers.name);
3421 curproxy->email_alert.mailers.name = strdup(args[2]);
3422 }
3423 else if (!strcmp(args[1], "myhostname")) {
3424 if (*(args[1]) == 0) {
3425 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3426 file, linenum, args[1]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430 free(curproxy->email_alert.myhostname);
3431 curproxy->email_alert.myhostname = strdup(args[2]);
3432 }
Simon Horman64e34162015-02-06 11:11:57 +09003433 else if (!strcmp(args[1], "level")) {
3434 curproxy->email_alert.level = get_log_level(args[2]);
3435 if (curproxy->email_alert.level < 0) {
3436 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3437 file, linenum, args[1], args[2]);
3438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
3440 }
3441 }
Simon Horman9dc49962015-01-30 11:22:59 +09003442 else if (!strcmp(args[1], "to")) {
3443 if (*(args[1]) == 0) {
3444 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3445 file, linenum, args[1]);
3446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
3448 }
3449 free(curproxy->email_alert.to);
3450 curproxy->email_alert.to = strdup(args[2]);
3451 }
3452 else {
3453 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3454 file, linenum, args[1]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
Simon Horman64e34162015-02-06 11:11:57 +09003458 /* Indicate that the email_alert is at least partially configured */
3459 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003460 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003461 else if (!strcmp(args[0], "external-check")) {
3462 if (*(args[1]) == 0) {
3463 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3464 file, linenum, args[0]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468
3469 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003470 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003471 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003472 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003473 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3474 file, linenum, args[1]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
3478 free(curproxy->check_command);
3479 curproxy->check_command = strdup(args[2]);
3480 }
3481 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003482 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003483 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003484 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003485 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3486 file, linenum, args[1]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
3490 free(curproxy->check_path);
3491 curproxy->check_path = strdup(args[2]);
3492 }
3493 else {
3494 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3495 file, linenum, args[1]);
3496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
3498 }
3499 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003500 else if (!strcmp(args[0], "persist")) { /* persist */
3501 if (*(args[1]) == 0) {
3502 Alert("parsing [%s:%d] : missing persist method.\n",
3503 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003506 }
3507
3508 if (!strncmp(args[1], "rdp-cookie", 10)) {
3509 curproxy->options2 |= PR_O2_RDPC_PRST;
3510
Emeric Brunb982a3d2010-01-04 15:45:53 +01003511 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003512 const char *beg, *end;
3513
3514 beg = args[1] + 11;
3515 end = strchr(beg, ')');
3516
William Lallemanddf1425a2015-04-28 20:17:49 +02003517 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3518 goto out;
3519
Emeric Brun647caf12009-06-30 17:57:00 +02003520 if (!end || end == beg) {
3521 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003525 }
3526
3527 free(curproxy->rdp_cookie_name);
3528 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3529 curproxy->rdp_cookie_len = end-beg;
3530 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003531 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003532 free(curproxy->rdp_cookie_name);
3533 curproxy->rdp_cookie_name = strdup("msts");
3534 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3535 }
3536 else { /* syntax */
3537 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3538 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003541 }
3542 }
3543 else {
3544 Alert("parsing [%s:%d] : unknown persist method.\n",
3545 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003548 }
3549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003551 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
3554 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003555 else if (!strcmp(args[0], "load-server-state-from-file")) {
3556 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3557 err_code |= ERR_WARN;
3558 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3559 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3560 }
3561 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3562 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3563 }
3564 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3565 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3566 }
3567 else {
3568 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3569 file, linenum, args[0], args[1]);
3570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
3572 }
3573 }
3574 else if (!strcmp(args[0], "server-state-file-name")) {
3575 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3576 err_code |= ERR_WARN;
3577 if (*(args[1]) == 0) {
3578 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3579 file, linenum, args[0]);
3580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
3582 }
3583 else if (!strcmp(args[1], "use-backend-name"))
3584 curproxy->server_state_file_name = strdup(curproxy->id);
3585 else
3586 curproxy->server_state_file_name = strdup(args[1]);
3587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003589 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003591
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003593 if (curproxy == &defproxy) {
3594 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
3597 }
3598
William Lallemand1a748ae2015-05-19 16:37:23 +02003599 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3600 goto out;
3601
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 if (*(args[4]) == 0) {
3603 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003608 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 curproxy->capture_name = strdup(args[2]);
3610 curproxy->capture_namelen = strlen(curproxy->capture_name);
3611 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 curproxy->to_log |= LW_COOKIE;
3613 }
3614 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3615 struct cap_hdr *hdr;
3616
3617 if (curproxy == &defproxy) {
3618 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 +02003619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 }
3622
William Lallemand1a748ae2015-05-19 16:37:23 +02003623 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3624 goto out;
3625
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3627 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3628 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 }
3632
Vincent Bernat02779b62016-04-03 13:48:43 +02003633 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 hdr->next = curproxy->req_cap;
3635 hdr->name = strdup(args[3]);
3636 hdr->namelen = strlen(args[3]);
3637 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003638 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 hdr->index = curproxy->nb_req_cap++;
3640 curproxy->req_cap = hdr;
3641 curproxy->to_log |= LW_REQHDR;
3642 }
3643 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3644 struct cap_hdr *hdr;
3645
3646 if (curproxy == &defproxy) {
3647 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 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
3651
William Lallemand1a748ae2015-05-19 16:37:23 +02003652 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3653 goto out;
3654
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3656 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3657 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003661 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 hdr->next = curproxy->rsp_cap;
3663 hdr->name = strdup(args[3]);
3664 hdr->namelen = strlen(args[3]);
3665 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003666 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 hdr->index = curproxy->nb_rsp_cap++;
3668 curproxy->rsp_cap = hdr;
3669 curproxy->to_log |= LW_RSPHDR;
3670 }
3671 else {
3672 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3673 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 }
3677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003679 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003681
William Lallemanddf1425a2015-04-28 20:17:49 +02003682 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3683 goto out;
3684
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 if (*(args[1]) == 0) {
3686 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3687 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 }
3691 curproxy->conn_retries = atol(args[1]);
3692 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003693 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003694 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003695
3696 if (curproxy == &defproxy) {
3697 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
3700 }
3701
Willy Tarreau20b0de52012-12-24 15:45:22 +01003702 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003703 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003704 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3705 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3706 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3707 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003708 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 +01003709 file, linenum, args[0]);
3710 err_code |= ERR_WARN;
3711 }
3712
Willy Tarreauff011f22011-01-06 17:51:27 +01003713 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003714
Willy Tarreauff011f22011-01-06 17:51:27 +01003715 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003716 err_code |= ERR_ALERT | ERR_ABORT;
3717 goto out;
3718 }
3719
Willy Tarreau5002f572014-04-23 01:32:02 +02003720 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003721 err_code |= warnif_cond_conflicts(rule->cond,
3722 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3723 file, linenum);
3724
Willy Tarreauff011f22011-01-06 17:51:27 +01003725 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003726 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003727 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003728 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003729
3730 if (curproxy == &defproxy) {
3731 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
3734 }
3735
3736 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003737 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003738 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3739 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003740 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3741 file, linenum, args[0]);
3742 err_code |= ERR_WARN;
3743 }
3744
3745 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3746
3747 if (!rule) {
3748 err_code |= ERR_ALERT | ERR_ABORT;
3749 goto out;
3750 }
3751
3752 err_code |= warnif_cond_conflicts(rule->cond,
3753 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3754 file, linenum);
3755
3756 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3757 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003758 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3759 /* set the header name and length into the proxy structure */
3760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3761 err_code |= ERR_WARN;
3762
3763 if (!*args[1]) {
3764 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3765 file, linenum, args[0]);
3766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
3768 }
3769
3770 /* set the desired header name */
3771 free(curproxy->server_id_hdr_name);
3772 curproxy->server_id_hdr_name = strdup(args[1]);
3773 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3774 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003775 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003776 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003777
Willy Tarreaub099aca2008-10-12 17:26:37 +02003778 if (curproxy == &defproxy) {
3779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003782 }
3783
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003784 /* emulate "block" using "http-request block". Since these rules are supposed to
3785 * be processed before all http-request rules, we put them into their own list
3786 * and will insert them at the end.
3787 */
3788 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3789 if (!rule) {
3790 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003791 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003792 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003793 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3794 err_code |= warnif_cond_conflicts(rule->cond,
3795 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3796 file, linenum);
3797 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003798
3799 if (!already_warned(WARN_BLOCK_DEPRECATED))
3800 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]);
3801
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003802 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003803 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003804 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003805
Cyril Bonté99ed3272010-01-24 23:29:44 +01003806 if (curproxy == &defproxy) {
3807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
3810 }
3811
Willy Tarreaube4653b2015-05-28 15:26:58 +02003812 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003813 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3814 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003817 }
3818
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003819 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003820 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003821 err_code |= warnif_cond_conflicts(rule->cond,
3822 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3823 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003824 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003825 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003826 struct switching_rule *rule;
3827
Willy Tarreaub099aca2008-10-12 17:26:37 +02003828 if (curproxy == &defproxy) {
3829 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003832 }
3833
Willy Tarreau55ea7572007-06-17 19:56:27 +02003834 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003836
3837 if (*(args[1]) == 0) {
3838 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003841 }
3842
Willy Tarreauf51658d2014-04-23 01:21:56 +02003843 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003844 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003845 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3846 file, linenum, errmsg);
3847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
3849 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003850
Willy Tarreauf51658d2014-04-23 01:21:56 +02003851 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003852 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003853 else if (*args[2]) {
3854 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3855 file, linenum, args[2]);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003859
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003860 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003861 if (!rule) {
3862 Alert("Out of memory error.\n");
3863 goto out;
3864 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003865 rule->cond = cond;
3866 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003867 rule->line = linenum;
3868 rule->file = strdup(file);
3869 if (!rule->file) {
3870 Alert("Out of memory error.\n");
3871 goto out;
3872 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003873 LIST_INIT(&rule->list);
3874 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3875 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003876 else if (strcmp(args[0], "use-server") == 0) {
3877 struct server_rule *rule;
3878
3879 if (curproxy == &defproxy) {
3880 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
3883 }
3884
3885 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3886 err_code |= ERR_WARN;
3887
3888 if (*(args[1]) == 0) {
3889 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
3892 }
3893
3894 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3895 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3896 file, linenum, args[0]);
3897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
3899 }
3900
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003901 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003902 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3903 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003908 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003909
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003910 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003911 rule->cond = cond;
3912 rule->srv.name = strdup(args[1]);
3913 LIST_INIT(&rule->list);
3914 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3915 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3916 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003917 else if ((!strcmp(args[0], "force-persist")) ||
3918 (!strcmp(args[0], "ignore-persist"))) {
3919 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003920
3921 if (curproxy == &defproxy) {
3922 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925 }
3926
3927 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3928 err_code |= ERR_WARN;
3929
Willy Tarreauef6494c2010-01-28 17:12:36 +01003930 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003931 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3932 file, linenum, args[0]);
3933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
3935 }
3936
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003937 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003938 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3939 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
3943
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003944 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3945 * where force-persist is applied.
3946 */
3947 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003948
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003949 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003950 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003951 if (!strcmp(args[0], "force-persist")) {
3952 rule->type = PERSIST_TYPE_FORCE;
3953 } else {
3954 rule->type = PERSIST_TYPE_IGNORE;
3955 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003956 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003957 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003958 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003959 else if (!strcmp(args[0], "stick-table")) {
3960 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003961 struct proxy *other;
3962
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003963 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003964 if (other) {
3965 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3966 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
3969 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003970
Emeric Brun32da3c42010-09-23 18:39:19 +02003971 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003972 curproxy->table.type = (unsigned int)-1;
3973 while (*args[myidx]) {
3974 const char *err;
3975
3976 if (strcmp(args[myidx], "size") == 0) {
3977 myidx++;
3978 if (!*(args[myidx])) {
3979 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3980 file, linenum, args[myidx-1]);
3981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
3983 }
3984 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3985 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3986 file, linenum, *err, args[myidx-1]);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003990 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003991 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003992 else if (strcmp(args[myidx], "peers") == 0) {
3993 myidx++;
Godbach50523162013-12-11 19:48:57 +08003994 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003995 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3996 file, linenum, args[myidx-1]);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Godbach50523162013-12-11 19:48:57 +08003999 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004000 curproxy->table.peers.name = strdup(args[myidx++]);
4001 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004002 else if (strcmp(args[myidx], "expire") == 0) {
4003 myidx++;
4004 if (!*(args[myidx])) {
4005 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4006 file, linenum, args[myidx-1]);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
4010 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4011 if (err) {
4012 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4013 file, linenum, *err, args[myidx-1]);
4014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004017 if (val > INT_MAX) {
4018 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4019 file, linenum, val);
4020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
4022 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004023 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004024 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004025 }
4026 else if (strcmp(args[myidx], "nopurge") == 0) {
4027 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004028 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004029 }
4030 else if (strcmp(args[myidx], "type") == 0) {
4031 myidx++;
4032 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4033 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4034 file, linenum, args[myidx]);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004038 /* myidx already points to next arg */
4039 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004040 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004041 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004042 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004043
4044 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004045 nw = args[myidx];
4046 while (*nw) {
4047 /* the "store" keyword supports a comma-separated list */
4048 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004049 sa = NULL; /* store arg */
4050 while (*nw && *nw != ',') {
4051 if (*nw == '(') {
4052 *nw = 0;
4053 sa = ++nw;
4054 while (*nw != ')') {
4055 if (!*nw) {
4056 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4057 file, linenum, args[0], cw);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061 nw++;
4062 }
4063 *nw = '\0';
4064 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004065 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004066 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004067 if (*nw)
4068 *nw++ = '\0';
4069 type = stktable_get_data_type(cw);
4070 if (type < 0) {
4071 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4072 file, linenum, args[0], cw);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
Willy Tarreauac782882010-06-20 10:41:54 +02004076
4077 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4078 switch (err) {
4079 case PE_NONE: break;
4080 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004081 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4082 file, linenum, args[0], cw);
4083 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004084 break;
4085
4086 case PE_ARG_MISSING:
4087 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4088 file, linenum, args[0], cw);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091
4092 case PE_ARG_NOT_USED:
4093 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4094 file, linenum, args[0], cw);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097
4098 default:
4099 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4100 file, linenum, args[0], cw);
4101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004103 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004104 }
4105 myidx++;
4106 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004107 else {
4108 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4109 file, linenum, args[myidx]);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004112 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113 }
4114
4115 if (!curproxy->table.size) {
4116 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4117 file, linenum);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121
4122 if (curproxy->table.type == (unsigned int)-1) {
4123 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4124 file, linenum);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128 }
4129 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004130 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004131 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 int myidx = 0;
4133 const char *name = NULL;
4134 int flags;
4135
4136 if (curproxy == &defproxy) {
4137 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
4140 }
4141
4142 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4143 err_code |= ERR_WARN;
4144 goto out;
4145 }
4146
4147 myidx++;
4148 if ((strcmp(args[myidx], "store") == 0) ||
4149 (strcmp(args[myidx], "store-request") == 0)) {
4150 myidx++;
4151 flags = STK_IS_STORE;
4152 }
4153 else if (strcmp(args[myidx], "store-response") == 0) {
4154 myidx++;
4155 flags = STK_IS_STORE | STK_ON_RSP;
4156 }
4157 else if (strcmp(args[myidx], "match") == 0) {
4158 myidx++;
4159 flags = STK_IS_MATCH;
4160 }
4161 else if (strcmp(args[myidx], "on") == 0) {
4162 myidx++;
4163 flags = STK_IS_MATCH | STK_IS_STORE;
4164 }
4165 else {
4166 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170
4171 if (*(args[myidx]) == 0) {
4172 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
4175 }
4176
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004177 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004178 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004179 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004180 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
4183 }
4184
4185 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004186 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4187 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4188 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004189 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004190 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004191 goto out;
4192 }
4193 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004194 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4195 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4196 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004197 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004198 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004199 goto out;
4200 }
4201 }
4202
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004203 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004204 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004205
Emeric Brunb982a3d2010-01-04 15:45:53 +01004206 if (strcmp(args[myidx], "table") == 0) {
4207 myidx++;
4208 name = args[myidx++];
4209 }
4210
Willy Tarreauef6494c2010-01-28 17:12:36 +01004211 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004212 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004213 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4214 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004215 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004216 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004217 goto out;
4218 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004219 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004220 else if (*(args[myidx])) {
4221 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4222 file, linenum, args[0], args[myidx]);
4223 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004224 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004225 goto out;
4226 }
Emeric Brun97679e72010-09-23 17:56:44 +02004227 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004228 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004229 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004230 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004231
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004232 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004233 rule->cond = cond;
4234 rule->expr = expr;
4235 rule->flags = flags;
4236 rule->table.name = name ? strdup(name) : NULL;
4237 LIST_INIT(&rule->list);
4238 if (flags & STK_ON_RSP)
4239 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4240 else
4241 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004243 else if (!strcmp(args[0], "stats")) {
4244 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4245 curproxy->uri_auth = NULL; /* we must detach from the default config */
4246
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004247 if (!*args[1]) {
4248 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004249 } else if (!strcmp(args[1], "admin")) {
4250 struct stats_admin_rule *rule;
4251
4252 if (curproxy == &defproxy) {
4253 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257
4258 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4259 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4260 err_code |= ERR_ALERT | ERR_ABORT;
4261 goto out;
4262 }
4263
4264 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4265 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4266 file, linenum, args[0], args[1]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004270 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004271 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4272 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 }
4276
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004277 err_code |= warnif_cond_conflicts(cond,
4278 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4279 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004280
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004281 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004282 rule->cond = cond;
4283 LIST_INIT(&rule->list);
4284 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 } else if (!strcmp(args[1], "uri")) {
4286 if (*(args[2]) == 0) {
4287 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4291 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004292 err_code |= ERR_ALERT | ERR_ABORT;
4293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 }
4295 } else if (!strcmp(args[1], "realm")) {
4296 if (*(args[2]) == 0) {
4297 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_ABORT;
4303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004305 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004306 unsigned interval;
4307
4308 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4309 if (err) {
4310 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4311 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004314 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4315 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004316 err_code |= ERR_ALERT | ERR_ABORT;
4317 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004318 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004319 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004320 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004321
4322 if (curproxy == &defproxy) {
4323 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
4326 }
4327
4328 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4329 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4330 err_code |= ERR_ALERT | ERR_ABORT;
4331 goto out;
4332 }
4333
Willy Tarreauff011f22011-01-06 17:51:27 +01004334 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004335 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004336 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4337 file, linenum, args[0]);
4338 err_code |= ERR_WARN;
4339 }
4340
Willy Tarreauff011f22011-01-06 17:51:27 +01004341 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004342
Willy Tarreauff011f22011-01-06 17:51:27 +01004343 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004344 err_code |= ERR_ALERT | ERR_ABORT;
4345 goto out;
4346 }
4347
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004348 err_code |= warnif_cond_conflicts(rule->cond,
4349 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4350 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004351 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004352
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 } else if (!strcmp(args[1], "auth")) {
4354 if (*(args[2]) == 0) {
4355 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004358 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_ABORT;
4361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 }
4363 } else if (!strcmp(args[1], "scope")) {
4364 if (*(args[2]) == 0) {
4365 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004368 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4369 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004370 err_code |= ERR_ALERT | ERR_ABORT;
4371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 }
4373 } else if (!strcmp(args[1], "enable")) {
4374 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4375 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_ALERT | ERR_ABORT;
4377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004379 } else if (!strcmp(args[1], "hide-version")) {
4380 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_ABORT;
4383 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004384 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004385 } else if (!strcmp(args[1], "show-legends")) {
4386 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4387 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4388 err_code |= ERR_ALERT | ERR_ABORT;
4389 goto out;
4390 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004391 } else if (!strcmp(args[1], "show-node")) {
4392
4393 if (*args[2]) {
4394 int i;
4395 char c;
4396
4397 for (i=0; args[2][i]; i++) {
4398 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004399 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4400 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004401 break;
4402 }
4403
4404 if (!i || args[2][i]) {
4405 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4406 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4407 file, linenum, args[0], args[1]);
4408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
4410 }
4411 }
4412
4413 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4414 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4415 err_code |= ERR_ALERT | ERR_ABORT;
4416 goto out;
4417 }
4418 } else if (!strcmp(args[1], "show-desc")) {
4419 char *desc = NULL;
4420
4421 if (*args[2]) {
4422 int i, len=0;
4423 char *d;
4424
Willy Tarreau348acfe2014-04-14 15:00:39 +02004425 for (i = 2; *args[i]; i++)
4426 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004427
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004428 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004429
Willy Tarreau348acfe2014-04-14 15:00:39 +02004430 d += snprintf(d, desc + len - d, "%s", args[2]);
4431 for (i = 3; *args[i]; i++)
4432 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004433 }
4434
4435 if (!*args[2] && !global.desc)
4436 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4437 file, linenum, args[1]);
4438 else {
4439 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4440 free(desc);
4441 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4442 err_code |= ERR_ALERT | ERR_ABORT;
4443 goto out;
4444 }
4445 free(desc);
4446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004448stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004449 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 +01004450 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 }
4454 }
4455 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004456 int optnum;
4457
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004458 if (*(args[1]) == '\0') {
4459 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004464
4465 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4466 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004467 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4468 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4469 file, linenum, cfg_opts[optnum].name);
4470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
4472 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004473 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4474 goto out;
4475
Willy Tarreau93893792009-07-23 13:19:11 +02004476 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4477 err_code |= ERR_WARN;
4478 goto out;
4479 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004480
Willy Tarreau3842f002009-06-14 11:39:52 +02004481 curproxy->no_options &= ~cfg_opts[optnum].val;
4482 curproxy->options &= ~cfg_opts[optnum].val;
4483
4484 switch (kwm) {
4485 case KWM_STD:
4486 curproxy->options |= cfg_opts[optnum].val;
4487 break;
4488 case KWM_NO:
4489 curproxy->no_options |= cfg_opts[optnum].val;
4490 break;
4491 case KWM_DEF: /* already cleared */
4492 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004493 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004494
Willy Tarreau93893792009-07-23 13:19:11 +02004495 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004496 }
4497 }
4498
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004499 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4500 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004501 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4502 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4503 file, linenum, cfg_opts2[optnum].name);
4504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004507 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4508 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004509 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4510 err_code |= ERR_WARN;
4511 goto out;
4512 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004513
Willy Tarreau3842f002009-06-14 11:39:52 +02004514 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4515 curproxy->options2 &= ~cfg_opts2[optnum].val;
4516
4517 switch (kwm) {
4518 case KWM_STD:
4519 curproxy->options2 |= cfg_opts2[optnum].val;
4520 break;
4521 case KWM_NO:
4522 curproxy->no_options2 |= cfg_opts2[optnum].val;
4523 break;
4524 case KWM_DEF: /* already cleared */
4525 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004526 }
Willy Tarreau93893792009-07-23 13:19:11 +02004527 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004528 }
4529 }
4530
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004531 /* HTTP options override each other. They can be cancelled using
4532 * "no option xxx" which only switches to default mode if the mode
4533 * was this one (useful for cancelling options set in defaults
4534 * sections).
4535 */
4536 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004537 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4538 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004539 if (kwm == KWM_STD) {
4540 curproxy->options &= ~PR_O_HTTP_MODE;
4541 curproxy->options |= PR_O_HTTP_PCL;
4542 goto out;
4543 }
4544 else if (kwm == KWM_NO) {
4545 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4546 curproxy->options &= ~PR_O_HTTP_MODE;
4547 goto out;
4548 }
4549 }
4550 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004551 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4552 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004553 if (kwm == KWM_STD) {
4554 curproxy->options &= ~PR_O_HTTP_MODE;
4555 curproxy->options |= PR_O_HTTP_FCL;
4556 goto out;
4557 }
4558 else if (kwm == KWM_NO) {
4559 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4560 curproxy->options &= ~PR_O_HTTP_MODE;
4561 goto out;
4562 }
4563 }
4564 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004565 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4566 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004567 if (kwm == KWM_STD) {
4568 curproxy->options &= ~PR_O_HTTP_MODE;
4569 curproxy->options |= PR_O_HTTP_SCL;
4570 goto out;
4571 }
4572 else if (kwm == KWM_NO) {
4573 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4574 curproxy->options &= ~PR_O_HTTP_MODE;
4575 goto out;
4576 }
4577 }
4578 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004579 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4580 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004581 if (kwm == KWM_STD) {
4582 curproxy->options &= ~PR_O_HTTP_MODE;
4583 curproxy->options |= PR_O_HTTP_KAL;
4584 goto out;
4585 }
4586 else if (kwm == KWM_NO) {
4587 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4588 curproxy->options &= ~PR_O_HTTP_MODE;
4589 goto out;
4590 }
4591 }
4592 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004593 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4594 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004595 if (kwm == KWM_STD) {
4596 curproxy->options &= ~PR_O_HTTP_MODE;
4597 curproxy->options |= PR_O_HTTP_TUN;
4598 goto out;
4599 }
4600 else if (kwm == KWM_NO) {
4601 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4602 curproxy->options &= ~PR_O_HTTP_MODE;
4603 goto out;
4604 }
4605 }
4606
Joseph Lynch726ab712015-05-11 23:25:34 -07004607 /* Redispatch can take an integer argument that control when the
4608 * resispatch occurs. All values are relative to the retries option.
4609 * This can be cancelled using "no option xxx".
4610 */
4611 if (strcmp(args[1], "redispatch") == 0) {
4612 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4613 err_code |= ERR_WARN;
4614 goto out;
4615 }
4616
4617 curproxy->no_options &= ~PR_O_REDISP;
4618 curproxy->options &= ~PR_O_REDISP;
4619
4620 switch (kwm) {
4621 case KWM_STD:
4622 curproxy->options |= PR_O_REDISP;
4623 curproxy->redispatch_after = -1;
4624 if(*args[2]) {
4625 curproxy->redispatch_after = atol(args[2]);
4626 }
4627 break;
4628 case KWM_NO:
4629 curproxy->no_options |= PR_O_REDISP;
4630 curproxy->redispatch_after = 0;
4631 break;
4632 case KWM_DEF: /* already cleared */
4633 break;
4634 }
4635 goto out;
4636 }
4637
Willy Tarreau3842f002009-06-14 11:39:52 +02004638 if (kwm != KWM_STD) {
4639 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004640 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004643 }
4644
Emeric Brun3a058f32009-06-30 18:26:00 +02004645 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004646 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004648 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004649 if (*(args[2]) != '\0') {
4650 if (!strcmp(args[2], "clf")) {
4651 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004652 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004653 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004654 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004657 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004658 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4659 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004660 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004661 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4662 char *oldlogformat = "log-format";
4663 char *clflogformat = "";
4664
4665 if (curproxy->conf.logformat_string == default_http_log_format)
4666 oldlogformat = "option httplog";
4667 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4668 oldlogformat = "option tcplog";
4669 else if (curproxy->conf.logformat_string == clf_http_log_format)
4670 oldlogformat = "option httplog clf";
4671 if (logformat == clf_http_log_format)
4672 clflogformat = " clf";
4673 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4674 file, linenum, clflogformat, oldlogformat);
4675 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004676 if (curproxy->conf.logformat_string != default_http_log_format &&
4677 curproxy->conf.logformat_string != default_tcp_log_format &&
4678 curproxy->conf.logformat_string != clf_http_log_format)
4679 free(curproxy->conf.logformat_string);
4680 curproxy->conf.logformat_string = logformat;
4681
4682 free(curproxy->conf.lfs_file);
4683 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4684 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004685 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004686 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004687 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4688 char *oldlogformat = "log-format";
4689
4690 if (curproxy->conf.logformat_string == default_http_log_format)
4691 oldlogformat = "option httplog";
4692 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4693 oldlogformat = "option tcplog";
4694 else if (curproxy->conf.logformat_string == clf_http_log_format)
4695 oldlogformat = "option httplog clf";
4696 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4697 file, linenum, oldlogformat);
4698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004700 if (curproxy->conf.logformat_string != default_http_log_format &&
4701 curproxy->conf.logformat_string != default_tcp_log_format &&
4702 curproxy->conf.logformat_string != clf_http_log_format)
4703 free(curproxy->conf.logformat_string);
4704 curproxy->conf.logformat_string = default_tcp_log_format;
4705
4706 free(curproxy->conf.lfs_file);
4707 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4708 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004709
4710 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4711 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004714 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004715 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004717
William Lallemanddf1425a2015-04-28 20:17:49 +02004718 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4719 goto out;
4720
Willy Tarreau13943ab2006-12-31 00:24:10 +01004721 if (curproxy->cap & PR_CAP_FE)
4722 curproxy->options |= PR_O_TCP_CLI_KA;
4723 if (curproxy->cap & PR_CAP_BE)
4724 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004725 }
4726 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004727 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004728 err_code |= ERR_WARN;
4729
Willy Tarreaubaaee002006-06-26 02:48:02 +02004730 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004731 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004732 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004733 curproxy->options2 &= ~PR_O2_CHK_ANY;
4734 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 if (!*args[2]) { /* no argument */
4736 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4737 curproxy->check_len = strlen(DEF_CHECK_REQ);
4738 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004739 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004740 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004742 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004744 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 if (*args[4])
4746 reqlen += strlen(args[4]);
4747 else
4748 reqlen += strlen("HTTP/1.0");
4749
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004750 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004752 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004754 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4755 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004756 }
4757 else if (!strcmp(args[1], "ssl-hello-chk")) {
4758 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004759 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004760 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004761
Willy Tarreaua534fea2008-08-03 12:19:50 +02004762 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004763 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004764 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004765 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004766
4767 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 }
Willy Tarreau23677902007-05-08 23:50:35 +02004770 else if (!strcmp(args[1], "smtpchk")) {
4771 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004772 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004773 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004774 curproxy->options2 &= ~PR_O2_CHK_ANY;
4775 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004776
4777 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4778 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4779 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4780 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4781 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4782 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004783 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004784 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4785 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4786 } else {
4787 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4788 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4789 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4790 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4791 }
4792 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004793 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4794 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004795 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004796 else if (!strcmp(args[1], "pgsql-check")) {
4797 /* use PostgreSQL request to check servers' health */
4798 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4799 err_code |= ERR_WARN;
4800
4801 free(curproxy->check_req);
4802 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004803 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004804 curproxy->options2 |= PR_O2_PGSQL_CHK;
4805
4806 if (*(args[2])) {
4807 int cur_arg = 2;
4808
4809 while (*(args[cur_arg])) {
4810 if (strcmp(args[cur_arg], "user") == 0) {
4811 char * packet;
4812 uint32_t packet_len;
4813 uint32_t pv;
4814
4815 /* suboption header - needs additional argument for it */
4816 if (*(args[cur_arg+1]) == 0) {
4817 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4818 file, linenum, args[0], args[1], args[cur_arg]);
4819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
4821 }
4822
4823 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4824 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4825 pv = htonl(0x30000); /* protocol version 3.0 */
4826
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004827 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004828
4829 memcpy(packet + 4, &pv, 4);
4830
4831 /* copy "user" */
4832 memcpy(packet + 8, "user", 4);
4833
4834 /* copy username */
4835 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4836
4837 free(curproxy->check_req);
4838 curproxy->check_req = packet;
4839 curproxy->check_len = packet_len;
4840
4841 packet_len = htonl(packet_len);
4842 memcpy(packet, &packet_len, 4);
4843 cur_arg += 2;
4844 } else {
4845 /* unknown suboption - catchall */
4846 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4847 file, linenum, args[0], args[1]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
4851 } /* end while loop */
4852 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004853 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4854 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004855 }
4856
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004857 else if (!strcmp(args[1], "redis-check")) {
4858 /* use REDIS PING request to check servers' health */
4859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4860 err_code |= ERR_WARN;
4861
4862 free(curproxy->check_req);
4863 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004864 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004865 curproxy->options2 |= PR_O2_REDIS_CHK;
4866
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004867 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004868 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4869 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004870
4871 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4872 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004873 }
4874
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004875 else if (!strcmp(args[1], "mysql-check")) {
4876 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004877 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4878 err_code |= ERR_WARN;
4879
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004880 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004881 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004882 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004883 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004884
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004885 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004886 * const char mysql40_client_auth_pkt[] = {
4887 * "\x0e\x00\x00" // packet length
4888 * "\x01" // packet number
4889 * "\x00\x00" // client capabilities
4890 * "\x00\x00\x01" // max packet
4891 * "haproxy\x00" // username (null terminated string)
4892 * "\x00" // filler (always 0x00)
4893 * "\x01\x00\x00" // packet length
4894 * "\x00" // packet number
4895 * "\x01" // COM_QUIT command
4896 * };
4897 */
4898
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004899 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4900 * const char mysql41_client_auth_pkt[] = {
4901 * "\x0e\x00\x00\" // packet length
4902 * "\x01" // packet number
4903 * "\x00\x00\x00\x00" // client capabilities
4904 * "\x00\x00\x00\x01" // max packet
4905 * "\x21" // character set (UTF-8)
4906 * char[23] // All zeroes
4907 * "haproxy\x00" // username (null terminated string)
4908 * "\x00" // filler (always 0x00)
4909 * "\x01\x00\x00" // packet length
4910 * "\x00" // packet number
4911 * "\x01" // COM_QUIT command
4912 * };
4913 */
4914
4915
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004916 if (*(args[2])) {
4917 int cur_arg = 2;
4918
4919 while (*(args[cur_arg])) {
4920 if (strcmp(args[cur_arg], "user") == 0) {
4921 char *mysqluser;
4922 int packetlen, reqlen, userlen;
4923
4924 /* suboption header - needs additional argument for it */
4925 if (*(args[cur_arg+1]) == 0) {
4926 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4927 file, linenum, args[0], args[1], args[cur_arg]);
4928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
4930 }
4931 mysqluser = args[cur_arg + 1];
4932 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004933
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004934 if (*(args[cur_arg+2])) {
4935 if (!strcmp(args[cur_arg+2], "post-41")) {
4936 packetlen = userlen + 7 + 27;
4937 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004938
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004939 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004940 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004941 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004942
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004943 snprintf(curproxy->check_req, 4, "%c%c%c",
4944 ((unsigned char) packetlen & 0xff),
4945 ((unsigned char) (packetlen >> 8) & 0xff),
4946 ((unsigned char) (packetlen >> 16) & 0xff));
4947
4948 curproxy->check_req[3] = 1;
4949 curproxy->check_req[5] = 130;
4950 curproxy->check_req[11] = 1;
4951 curproxy->check_req[12] = 33;
4952 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4953 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4954 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4955 cur_arg += 3;
4956 } else {
4957 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
4960 }
4961 } else {
4962 packetlen = userlen + 7;
4963 reqlen = packetlen + 9;
4964
4965 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004966 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004967 curproxy->check_len = reqlen;
4968
4969 snprintf(curproxy->check_req, 4, "%c%c%c",
4970 ((unsigned char) packetlen & 0xff),
4971 ((unsigned char) (packetlen >> 8) & 0xff),
4972 ((unsigned char) (packetlen >> 16) & 0xff));
4973
4974 curproxy->check_req[3] = 1;
4975 curproxy->check_req[5] = 128;
4976 curproxy->check_req[8] = 1;
4977 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4978 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4979 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4980 cur_arg += 2;
4981 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004982 } else {
4983 /* unknown suboption - catchall */
4984 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4985 file, linenum, args[0], args[1]);
4986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
4988 }
4989 } /* end while loop */
4990 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004991 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004992 else if (!strcmp(args[1], "ldap-check")) {
4993 /* use LDAP request to check servers' health */
4994 free(curproxy->check_req);
4995 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004996 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004997 curproxy->options2 |= PR_O2_LDAP_CHK;
4998
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004999 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005000 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5001 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005002 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5003 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005004 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005005 else if (!strcmp(args[1], "spop-check")) {
5006 if (curproxy == &defproxy) {
5007 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5008 file, linenum, args[0], args[1]);
5009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
5011 }
5012 if (curproxy->cap & PR_CAP_FE) {
5013 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5014 file, linenum, args[0], args[1]);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
5018
5019 /* use SPOE request to check servers' health */
5020 free(curproxy->check_req);
5021 curproxy->check_req = NULL;
5022 curproxy->options2 &= ~PR_O2_CHK_ANY;
5023 curproxy->options2 |= PR_O2_SPOP_CHK;
5024
Christopher Faulet8ef75252017-02-20 22:56:03 +01005025 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005026 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
5029 }
5030 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5031 goto out;
5032 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005033 else if (!strcmp(args[1], "tcp-check")) {
5034 /* use raw TCPCHK send/expect to check servers' health */
5035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5036 err_code |= ERR_WARN;
5037
5038 free(curproxy->check_req);
5039 curproxy->check_req = NULL;
5040 curproxy->options2 &= ~PR_O2_CHK_ANY;
5041 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005042 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5043 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005044 }
Simon Horman98637e52014-06-20 12:30:16 +09005045 else if (!strcmp(args[1], "external-check")) {
5046 /* excute an external command to check servers' health */
5047 free(curproxy->check_req);
5048 curproxy->check_req = NULL;
5049 curproxy->options2 &= ~PR_O2_CHK_ANY;
5050 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005051 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5052 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005053 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005054 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005055 int cur_arg;
5056
5057 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5058 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005059 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005060
Willy Tarreau87cf5142011-08-19 22:57:24 +02005061 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005062
5063 free(curproxy->fwdfor_hdr_name);
5064 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5065 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5066
5067 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5068 cur_arg = 2;
5069 while (*(args[cur_arg])) {
5070 if (!strcmp(args[cur_arg], "except")) {
5071 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005072 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005073 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5074 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005075 err_code |= ERR_ALERT | ERR_FATAL;
5076 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005077 }
5078 /* flush useless bits */
5079 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005080 cur_arg += 2;
5081 } else if (!strcmp(args[cur_arg], "header")) {
5082 /* suboption header - needs additional argument for it */
5083 if (*(args[cur_arg+1]) == 0) {
5084 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5085 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005088 }
5089 free(curproxy->fwdfor_hdr_name);
5090 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5091 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5092 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005093 } else if (!strcmp(args[cur_arg], "if-none")) {
5094 curproxy->options &= ~PR_O_FF_ALWAYS;
5095 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005096 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005097 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005098 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005099 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005102 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005103 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005104 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005105 else if (!strcmp(args[1], "originalto")) {
5106 int cur_arg;
5107
5108 /* insert x-original-to field, but not for the IP address listed as an except.
5109 * set default options (ie: bitfield, header name, etc)
5110 */
5111
5112 curproxy->options |= PR_O_ORGTO;
5113
5114 free(curproxy->orgto_hdr_name);
5115 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5116 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5117
Willy Tarreau87cf5142011-08-19 22:57:24 +02005118 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005119 cur_arg = 2;
5120 while (*(args[cur_arg])) {
5121 if (!strcmp(args[cur_arg], "except")) {
5122 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005123 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 +02005124 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5125 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005128 }
5129 /* flush useless bits */
5130 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5131 cur_arg += 2;
5132 } else if (!strcmp(args[cur_arg], "header")) {
5133 /* suboption header - needs additional argument for it */
5134 if (*(args[cur_arg+1]) == 0) {
5135 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5136 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005139 }
5140 free(curproxy->orgto_hdr_name);
5141 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5142 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5143 cur_arg += 2;
5144 } else {
5145 /* unknown suboption - catchall */
5146 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5147 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005150 }
5151 } /* end while loop */
5152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 else {
5154 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
Willy Tarreau93893792009-07-23 13:19:11 +02005158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005160 else if (!strcmp(args[0], "default_backend")) {
5161 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005162 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005163
5164 if (*(args[1]) == 0) {
5165 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005168 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005169 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005170 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005171
5172 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5173 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005176 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005178
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005179 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5180 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 +01005181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 /* enable reconnections to dispatch */
5184 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005185
5186 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005189 else if (!strcmp(args[0], "http-reuse")) {
5190 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5191 err_code |= ERR_WARN;
5192
5193 if (strcmp(args[1], "never") == 0) {
5194 /* enable a graceful server shutdown on an HTTP 404 response */
5195 curproxy->options &= ~PR_O_REUSE_MASK;
5196 curproxy->options |= PR_O_REUSE_NEVR;
5197 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5198 goto out;
5199 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005200 else if (strcmp(args[1], "safe") == 0) {
5201 /* enable a graceful server shutdown on an HTTP 404 response */
5202 curproxy->options &= ~PR_O_REUSE_MASK;
5203 curproxy->options |= PR_O_REUSE_SAFE;
5204 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5205 goto out;
5206 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005207 else if (strcmp(args[1], "aggressive") == 0) {
5208 curproxy->options &= ~PR_O_REUSE_MASK;
5209 curproxy->options |= PR_O_REUSE_AGGR;
5210 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5211 goto out;
5212 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005213 else if (strcmp(args[1], "always") == 0) {
5214 /* enable a graceful server shutdown on an HTTP 404 response */
5215 curproxy->options &= ~PR_O_REUSE_MASK;
5216 curproxy->options |= PR_O_REUSE_ALWS;
5217 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5218 goto out;
5219 }
5220 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005221 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
5225 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005226 else if (!strcmp(args[0], "http-check")) {
5227 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005228 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005229
5230 if (strcmp(args[1], "disable-on-404") == 0) {
5231 /* enable a graceful server shutdown on an HTTP 404 response */
5232 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005233 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5234 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005235 }
Willy Tarreauef781042010-01-27 11:53:01 +01005236 else if (strcmp(args[1], "send-state") == 0) {
5237 /* enable emission of the apparent state of a server in HTTP checks */
5238 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005239 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5240 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005241 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005242 else if (strcmp(args[1], "expect") == 0) {
5243 const char *ptr_arg;
5244 int cur_arg;
5245
5246 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5247 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251
5252 cur_arg = 2;
5253 /* consider exclamation marks, sole or at the beginning of a word */
5254 while (*(ptr_arg = args[cur_arg])) {
5255 while (*ptr_arg == '!') {
5256 curproxy->options2 ^= PR_O2_EXP_INV;
5257 ptr_arg++;
5258 }
5259 if (*ptr_arg)
5260 break;
5261 cur_arg++;
5262 }
5263 /* now ptr_arg points to the beginning of a word past any possible
5264 * exclamation mark, and cur_arg is the argument which holds this word.
5265 */
5266 if (strcmp(ptr_arg, "status") == 0) {
5267 if (!*(args[cur_arg + 1])) {
5268 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5269 file, linenum, args[0], args[1], ptr_arg);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272 }
5273 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005274 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005275 curproxy->expect_str = strdup(args[cur_arg + 1]);
5276 }
5277 else if (strcmp(ptr_arg, "string") == 0) {
5278 if (!*(args[cur_arg + 1])) {
5279 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5280 file, linenum, args[0], args[1], ptr_arg);
5281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
5283 }
5284 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005285 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005286 curproxy->expect_str = strdup(args[cur_arg + 1]);
5287 }
5288 else if (strcmp(ptr_arg, "rstatus") == 0) {
5289 if (!*(args[cur_arg + 1])) {
5290 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5291 file, linenum, args[0], args[1], ptr_arg);
5292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
5294 }
5295 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005296 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005297 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005298 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005299 free(curproxy->expect_regex);
5300 curproxy->expect_regex = NULL;
5301 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005302 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005303 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5304 error = NULL;
5305 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5306 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5307 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5308 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
5312 }
5313 else if (strcmp(ptr_arg, "rstring") == 0) {
5314 if (!*(args[cur_arg + 1])) {
5315 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5316 file, linenum, args[0], args[1], ptr_arg);
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005321 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005322 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005323 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005324 free(curproxy->expect_regex);
5325 curproxy->expect_regex = NULL;
5326 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005327 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005328 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5329 error = NULL;
5330 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5331 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5332 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5333 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
5337 }
5338 else {
5339 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5340 file, linenum, args[0], args[1], ptr_arg);
5341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
5343 }
5344 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005345 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005346 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 +02005347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005349 }
5350 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005351 else if (!strcmp(args[0], "tcp-check")) {
5352 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5353 err_code |= ERR_WARN;
5354
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005355 if (strcmp(args[1], "comment") == 0) {
5356 int cur_arg;
5357 struct tcpcheck_rule *tcpcheck;
5358
5359 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005360 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005361 tcpcheck->action = TCPCHK_ACT_COMMENT;
5362
5363 if (!*args[cur_arg + 1]) {
5364 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5365 file, linenum, args[cur_arg]);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369
5370 tcpcheck->comment = strdup(args[cur_arg + 1]);
5371
5372 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005373 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5374 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005375 }
5376 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005377 const char *ptr_arg;
5378 int cur_arg;
5379 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005380
5381 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005382 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5383 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5384 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5385 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5386 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005387
Willy Tarreau5581c272015-05-13 12:24:53 +02005388 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5389 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5390 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5391 file, linenum);
5392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005394 }
5395
5396 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005397 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005398 tcpcheck->action = TCPCHK_ACT_CONNECT;
5399
5400 /* parsing each parameters to fill up the rule */
5401 while (*(ptr_arg = args[cur_arg])) {
5402 /* tcp port */
5403 if (strcmp(args[cur_arg], "port") == 0) {
5404 if ( (atol(args[cur_arg + 1]) > 65535) ||
5405 (atol(args[cur_arg + 1]) < 1) ){
5406 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5407 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411 tcpcheck->port = atol(args[cur_arg + 1]);
5412 cur_arg += 2;
5413 }
5414 /* send proxy protocol */
5415 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5416 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5417 cur_arg++;
5418 }
5419#ifdef USE_OPENSSL
5420 else if (strcmp(args[cur_arg], "ssl") == 0) {
5421 curproxy->options |= PR_O_TCPCHK_SSL;
5422 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5423 cur_arg++;
5424 }
5425#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005426 /* comment for this tcpcheck line */
5427 else if (strcmp(args[cur_arg], "comment") == 0) {
5428 if (!*args[cur_arg + 1]) {
5429 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5430 file, linenum, args[cur_arg]);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
5434 tcpcheck->comment = strdup(args[cur_arg + 1]);
5435 cur_arg += 2;
5436 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005437 else {
5438#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005439 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 +01005440#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005441 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 +01005442#endif /* USE_OPENSSL */
5443 file, linenum, args[0], args[1], args[cur_arg]);
5444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
5447
5448 }
5449
5450 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5451 }
5452 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005453 if (! *(args[2]) ) {
5454 /* SEND string expected */
5455 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5456 file, linenum, args[0], args[1], args[2]);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 } else {
5460 struct tcpcheck_rule *tcpcheck;
5461
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005462 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005463
5464 tcpcheck->action = TCPCHK_ACT_SEND;
5465 tcpcheck->string_len = strlen(args[2]);
5466 tcpcheck->string = strdup(args[2]);
5467 tcpcheck->expect_regex = NULL;
5468
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005469 /* comment for this tcpcheck line */
5470 if (strcmp(args[3], "comment") == 0) {
5471 if (!*args[4]) {
5472 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5473 file, linenum, args[3]);
5474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
5476 }
5477 tcpcheck->comment = strdup(args[4]);
5478 }
5479
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005480 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5481 }
5482 }
5483 else if (strcmp(args[1], "send-binary") == 0) {
5484 if (! *(args[2]) ) {
5485 /* SEND binary string expected */
5486 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5487 file, linenum, args[0], args[1], args[2]);
5488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
5490 } else {
5491 struct tcpcheck_rule *tcpcheck;
5492 char *err = NULL;
5493
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005494 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005495
5496 tcpcheck->action = TCPCHK_ACT_SEND;
5497 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5498 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5499 file, linenum, args[0], args[1], args[2], err);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 tcpcheck->expect_regex = NULL;
5504
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005505 /* comment for this tcpcheck line */
5506 if (strcmp(args[3], "comment") == 0) {
5507 if (!*args[4]) {
5508 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5509 file, linenum, args[3]);
5510 err_code |= ERR_ALERT | ERR_FATAL;
5511 goto out;
5512 }
5513 tcpcheck->comment = strdup(args[4]);
5514 }
5515
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005516 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5517 }
5518 }
5519 else if (strcmp(args[1], "expect") == 0) {
5520 const char *ptr_arg;
5521 int cur_arg;
5522 int inverse = 0;
5523
5524 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5525 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
5528 }
5529
5530 cur_arg = 2;
5531 /* consider exclamation marks, sole or at the beginning of a word */
5532 while (*(ptr_arg = args[cur_arg])) {
5533 while (*ptr_arg == '!') {
5534 inverse = !inverse;
5535 ptr_arg++;
5536 }
5537 if (*ptr_arg)
5538 break;
5539 cur_arg++;
5540 }
5541 /* now ptr_arg points to the beginning of a word past any possible
5542 * exclamation mark, and cur_arg is the argument which holds this word.
5543 */
5544 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005545 struct tcpcheck_rule *tcpcheck;
5546 char *err = NULL;
5547
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005548 if (!*(args[cur_arg + 1])) {
5549 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5550 file, linenum, args[0], args[1], ptr_arg);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005554
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005555 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005556
5557 tcpcheck->action = TCPCHK_ACT_EXPECT;
5558 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5559 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5560 file, linenum, args[0], args[1], args[2], err);
5561 err_code |= ERR_ALERT | ERR_FATAL;
5562 goto out;
5563 }
5564 tcpcheck->expect_regex = NULL;
5565 tcpcheck->inverse = inverse;
5566
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005567 /* tcpcheck comment */
5568 cur_arg += 2;
5569 if (strcmp(args[cur_arg], "comment") == 0) {
5570 if (!*args[cur_arg + 1]) {
5571 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5572 file, linenum, args[cur_arg + 1]);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
5576 tcpcheck->comment = strdup(args[cur_arg + 1]);
5577 }
5578
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005579 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5580 }
5581 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005582 struct tcpcheck_rule *tcpcheck;
5583
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005584 if (!*(args[cur_arg + 1])) {
5585 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5586 file, linenum, args[0], args[1], ptr_arg);
5587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
5589 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005590
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005591 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005592
5593 tcpcheck->action = TCPCHK_ACT_EXPECT;
5594 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5595 tcpcheck->string = strdup(args[cur_arg + 1]);
5596 tcpcheck->expect_regex = NULL;
5597 tcpcheck->inverse = inverse;
5598
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005599 /* tcpcheck comment */
5600 cur_arg += 2;
5601 if (strcmp(args[cur_arg], "comment") == 0) {
5602 if (!*args[cur_arg + 1]) {
5603 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5604 file, linenum, args[cur_arg + 1]);
5605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 }
5608 tcpcheck->comment = strdup(args[cur_arg + 1]);
5609 }
5610
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005611 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5612 }
5613 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005614 struct tcpcheck_rule *tcpcheck;
5615
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005616 if (!*(args[cur_arg + 1])) {
5617 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5618 file, linenum, args[0], args[1], ptr_arg);
5619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005622
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005623 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005624
5625 tcpcheck->action = TCPCHK_ACT_EXPECT;
5626 tcpcheck->string_len = 0;
5627 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005628 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5629 error = NULL;
5630 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5631 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5632 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5633 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
5636 }
5637 tcpcheck->inverse = inverse;
5638
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005639 /* tcpcheck comment */
5640 cur_arg += 2;
5641 if (strcmp(args[cur_arg], "comment") == 0) {
5642 if (!*args[cur_arg + 1]) {
5643 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5644 file, linenum, args[cur_arg + 1]);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
5648 tcpcheck->comment = strdup(args[cur_arg + 1]);
5649 }
5650
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005651 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5652 }
5653 else {
5654 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5655 file, linenum, args[0], args[1], ptr_arg);
5656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
5658 }
5659 }
5660 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005661 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005662 err_code |= ERR_ALERT | ERR_FATAL;
5663 goto out;
5664 }
5665 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005666 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005667 if (curproxy == &defproxy) {
5668 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005669 err_code |= ERR_ALERT | ERR_FATAL;
5670 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005671 }
5672
Willy Tarreaub80c2302007-11-30 20:51:32 +01005673 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005674 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005675
5676 if (strcmp(args[1], "fail") == 0) {
5677 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005678 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005679 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5680 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005681 err_code |= ERR_ALERT | ERR_FATAL;
5682 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005683 }
5684
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005685 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005686 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5687 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005690 }
5691 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5692 }
5693 else {
5694 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005695 err_code |= ERR_ALERT | ERR_FATAL;
5696 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005697 }
5698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699#ifdef TPROXY
5700 else if (!strcmp(args[0], "transparent")) {
5701 /* enable transparent proxy connections */
5702 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005703 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
5706#endif
5707 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005708 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005709 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005710
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 if (*(args[1]) == 0) {
5712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 }
5716 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005720 else if (!strcmp(args[0], "backlog")) { /* backlog */
5721 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005722 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005723
5724 if (*(args[1]) == 0) {
5725 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005726 err_code |= ERR_ALERT | ERR_FATAL;
5727 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005728 }
5729 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5731 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005732 }
Willy Tarreau86034312006-12-29 00:10:33 +01005733 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005734 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005735 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005736
Willy Tarreau86034312006-12-29 00:10:33 +01005737 if (*(args[1]) == 0) {
5738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005739 err_code |= ERR_ALERT | ERR_FATAL;
5740 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005741 }
5742 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005743 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5744 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5747 if (*(args[1]) == 0) {
5748 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005752 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5753 if (err) {
5754 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5755 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005758 }
5759 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 }
5763 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005764 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005765 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005766 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005767
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 if (curproxy == &defproxy) {
5769 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005770 err_code |= ERR_ALERT | ERR_FATAL;
5771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005773 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005774 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005775
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005776 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005777 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005778 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005779 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005780 goto out;
5781 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005782
5783 proto = protocol_by_family(sk->ss_family);
5784 if (!proto || !proto->connect) {
5785 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5786 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005787 err_code |= ERR_ALERT | ERR_FATAL;
5788 goto out;
5789 }
5790
5791 if (port1 != port2) {
5792 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5793 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005794 err_code |= ERR_ALERT | ERR_FATAL;
5795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005797
5798 if (!port1) {
5799 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5800 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005801 err_code |= ERR_ALERT | ERR_FATAL;
5802 goto out;
5803 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005804
William Lallemanddf1425a2015-04-28 20:17:49 +02005805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5806 goto out;
5807
Willy Tarreaud5191e72010-02-09 20:50:45 +01005808 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005809 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 }
5811 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005812 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005813 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005814
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005815 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5816 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005821 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005822 /**
5823 * The syntax for hash-type config element is
5824 * hash-type {map-based|consistent} [[<algo>] avalanche]
5825 *
5826 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5827 */
5828 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005829
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005830 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5831 err_code |= ERR_WARN;
5832
5833 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005834 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5835 }
5836 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005837 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5838 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005839 else if (strcmp(args[1], "avalanche") == 0) {
5840 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]);
5841 err_code |= ERR_ALERT | ERR_FATAL;
5842 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005843 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005844 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005845 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
5848 }
Bhaskar98634f02013-10-29 23:30:51 -04005849
5850 /* set the hash function to use */
5851 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005852 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005853 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005854
5855 /* if consistent with no argument, then avalanche modifier is also applied */
5856 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5857 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005858 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005859 /* set the hash function */
5860 if (!strcmp(args[2], "sdbm")) {
5861 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5862 }
5863 else if (!strcmp(args[2], "djb2")) {
5864 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005865 }
5866 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005867 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005868 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005869 else if (!strcmp(args[2], "crc32")) {
5870 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5871 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005872 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005873 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 -05005874 err_code |= ERR_ALERT | ERR_FATAL;
5875 goto out;
5876 }
5877
5878 /* set the hash modifier */
5879 if (!strcmp(args[3], "avalanche")) {
5880 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5881 }
5882 else if (*args[3]) {
5883 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5884 err_code |= ERR_ALERT | ERR_FATAL;
5885 goto out;
5886 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005887 }
William Lallemanda73203e2012-03-12 12:48:57 +01005888 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005889 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5890 if (*(args[1]) == 0) {
5891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5892 err_code |= ERR_ALERT | ERR_FATAL;
5893 goto out;
5894 }
5895 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5896 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5897 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5898 err_code |= ERR_ALERT | ERR_FATAL;
5899 goto out;
5900 }
5901 }
William Lallemanda73203e2012-03-12 12:48:57 +01005902 else if (strcmp(args[0], "unique-id-format") == 0) {
5903 if (!*(args[1])) {
5904 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5905 err_code |= ERR_ALERT | ERR_FATAL;
5906 goto out;
5907 }
William Lallemand3203ff42012-11-11 17:30:56 +01005908 if (*(args[2])) {
5909 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
5912 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005913 free(curproxy->conf.uniqueid_format_string);
5914 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005915
Willy Tarreau62a61232013-04-12 18:13:46 +02005916 free(curproxy->conf.uif_file);
5917 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5918 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005919 }
William Lallemanda73203e2012-03-12 12:48:57 +01005920
5921 else if (strcmp(args[0], "unique-id-header") == 0) {
5922 if (!*(args[1])) {
5923 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5924 err_code |= ERR_ALERT | ERR_FATAL;
5925 goto out;
5926 }
5927 free(curproxy->header_unique_id);
5928 curproxy->header_unique_id = strdup(args[1]);
5929 }
5930
William Lallemand723b73a2012-02-08 16:37:49 +01005931 else if (strcmp(args[0], "log-format") == 0) {
5932 if (!*(args[1])) {
5933 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
5936 }
William Lallemand3203ff42012-11-11 17:30:56 +01005937 if (*(args[2])) {
5938 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5939 err_code |= ERR_ALERT | ERR_FATAL;
5940 goto out;
5941 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005942 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5943 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005944
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005945 if (curproxy->conf.logformat_string == default_http_log_format)
5946 oldlogformat = "option httplog";
5947 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5948 oldlogformat = "option tcplog";
5949 else if (curproxy->conf.logformat_string == clf_http_log_format)
5950 oldlogformat = "option httplog clf";
5951 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5952 file, linenum, oldlogformat);
5953 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005954 if (curproxy->conf.logformat_string != default_http_log_format &&
5955 curproxy->conf.logformat_string != default_tcp_log_format &&
5956 curproxy->conf.logformat_string != clf_http_log_format)
5957 free(curproxy->conf.logformat_string);
5958 curproxy->conf.logformat_string = strdup(args[1]);
5959
5960 free(curproxy->conf.lfs_file);
5961 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5962 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005963
5964 /* get a chance to improve log-format error reporting by
5965 * reporting the correct line-number when possible.
5966 */
5967 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5968 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5969 file, linenum, curproxy->id);
5970 err_code |= ERR_WARN;
5971 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005973 else if (!strcmp(args[0], "log-format-sd")) {
5974 if (!*(args[1])) {
5975 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5976 err_code |= ERR_ALERT | ERR_FATAL;
5977 goto out;
5978 }
5979 if (*(args[2])) {
5980 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5981 err_code |= ERR_ALERT | ERR_FATAL;
5982 goto out;
5983 }
5984
5985 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5986 free(curproxy->conf.logformat_sd_string);
5987 curproxy->conf.logformat_sd_string = strdup(args[1]);
5988
5989 free(curproxy->conf.lfsd_file);
5990 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5991 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5992
5993 /* get a chance to improve log-format-sd error reporting by
5994 * reporting the correct line-number when possible.
5995 */
5996 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5997 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5998 file, linenum, curproxy->id);
5999 err_code |= ERR_WARN;
6000 }
6001 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006002 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6003 if (*(args[1]) == 0) {
6004 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6005 err_code |= ERR_ALERT | ERR_FATAL;
6006 goto out;
6007 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006008 chunk_destroy(&curproxy->log_tag);
6009 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006010 }
William Lallemand0f99e342011-10-12 17:50:54 +02006011 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6012 /* delete previous herited or defined syslog servers */
6013 struct logsrv *back;
6014
6015 if (*(args[1]) != 0) {
6016 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
6019 }
6020
William Lallemand723b73a2012-02-08 16:37:49 +01006021 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6022 LIST_DEL(&tmplogsrv->list);
6023 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006024 }
6025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006027 struct logsrv *logsrv;
6028
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006030 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006031 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006032 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006033 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006034 LIST_INIT(&node->list);
6035 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037 }
6038 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006039 struct sockaddr_storage *sk;
6040 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006041 int arg = 0;
6042 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006043
Vincent Bernat02779b62016-04-03 13:48:43 +02006044 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045
Willy Tarreau18324f52014-06-27 18:10:07 +02006046 /* just after the address, a length may be specified */
6047 if (strcmp(args[arg+2], "len") == 0) {
6048 len = atoi(args[arg+3]);
6049 if (len < 80 || len > 65535) {
6050 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6051 file, linenum, args[arg+3]);
6052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
6054 }
6055 logsrv->maxlen = len;
6056
6057 /* skip these two args */
6058 arg += 2;
6059 }
6060 else
6061 logsrv->maxlen = MAX_SYSLOG_LEN;
6062
Christopher Faulet084aa962017-08-29 16:54:41 +02006063 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006064 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006065
Dragan Dosen1322d092015-09-22 16:05:32 +02006066 /* after the length, a format may be specified */
6067 if (strcmp(args[arg+2], "format") == 0) {
6068 logsrv->format = get_log_format(args[arg+3]);
6069 if (logsrv->format < 0) {
6070 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6071 err_code |= ERR_ALERT | ERR_FATAL;
6072 goto out;
6073 }
6074
6075 /* skip these two args */
6076 arg += 2;
6077 }
6078
William Lallemanddf1425a2015-04-28 20:17:49 +02006079 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6080 goto out;
6081
Willy Tarreau18324f52014-06-27 18:10:07 +02006082 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006083 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006084 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006085 err_code |= ERR_ALERT | ERR_FATAL;
6086 goto out;
6087
Willy Tarreaubaaee002006-06-26 02:48:02 +02006088 }
6089
William Lallemand0f99e342011-10-12 17:50:54 +02006090 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006091 if (*(args[arg+3])) {
6092 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006093 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006094 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
6097
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 }
6099 }
6100
William Lallemand0f99e342011-10-12 17:50:54 +02006101 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006102 if (*(args[arg+4])) {
6103 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006104 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006105 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006106 err_code |= ERR_ALERT | ERR_FATAL;
6107 goto out;
6108
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006109 }
6110 }
6111
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006112 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006113 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006114 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006115 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006116 goto out;
6117 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006118
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006119 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006120
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006121 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006122 if (port1 != port2) {
6123 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6124 file, linenum, args[0], args[1]);
6125 err_code |= ERR_ALERT | ERR_FATAL;
6126 goto out;
6127 }
6128
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006129 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006130 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 }
William Lallemand0f99e342011-10-12 17:50:54 +02006132
6133 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 }
6135 else {
6136 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6137 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 }
6141 }
6142 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006143 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006144 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006145 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006146 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006147
Willy Tarreau977b8e42006-12-29 14:19:17 +01006148 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006149 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006150
Willy Tarreaubaaee002006-06-26 02:48:02 +02006151 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006152 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6153 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006157
6158 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006159 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6160 free(curproxy->conn_src.iface_name);
6161 curproxy->conn_src.iface_name = NULL;
6162 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006163
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006164 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006165 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006166 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006167 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006168 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006169 goto out;
6170 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006171
6172 proto = protocol_by_family(sk->ss_family);
6173 if (!proto || !proto->connect) {
6174 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006175 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006176 err_code |= ERR_ALERT | ERR_FATAL;
6177 goto out;
6178 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006179
6180 if (port1 != port2) {
6181 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6182 file, linenum, args[0], args[1]);
6183 err_code |= ERR_ALERT | ERR_FATAL;
6184 goto out;
6185 }
6186
Willy Tarreauef9a3602012-12-08 22:29:20 +01006187 curproxy->conn_src.source_addr = *sk;
6188 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006189
6190 cur_arg = 2;
6191 while (*(args[cur_arg])) {
6192 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006193#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006194 if (!*args[cur_arg + 1]) {
6195 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6196 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006197 err_code |= ERR_ALERT | ERR_FATAL;
6198 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006199 }
6200
6201 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006202 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6203 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006204 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006205 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6206 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006207 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6208 char *name, *end;
6209
6210 name = args[cur_arg+1] + 7;
6211 while (isspace(*name))
6212 name++;
6213
6214 end = name;
6215 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6216 end++;
6217
Willy Tarreauef9a3602012-12-08 22:29:20 +01006218 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6219 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6220 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6221 curproxy->conn_src.bind_hdr_len = end - name;
6222 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6223 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6224 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006225
6226 /* now look for an occurrence number */
6227 while (isspace(*end))
6228 end++;
6229 if (*end == ',') {
6230 end++;
6231 name = end;
6232 if (*end == '-')
6233 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006234 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006235 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006236 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006237 }
6238
Willy Tarreauef9a3602012-12-08 22:29:20 +01006239 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006240 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6241 " occurrences values smaller than %d.\n",
6242 file, linenum, MAX_HDR_HISTORY);
6243 err_code |= ERR_ALERT | ERR_FATAL;
6244 goto out;
6245 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006246 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006247 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006248
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006249 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006250 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006251 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006252 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006253 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006254 goto out;
6255 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006256
6257 proto = protocol_by_family(sk->ss_family);
6258 if (!proto || !proto->connect) {
6259 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6260 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006261 err_code |= ERR_ALERT | ERR_FATAL;
6262 goto out;
6263 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006264
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006265 if (port1 != port2) {
6266 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6267 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006268 err_code |= ERR_ALERT | ERR_FATAL;
6269 goto out;
6270 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006271 curproxy->conn_src.tproxy_addr = *sk;
6272 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006273 }
6274 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006275#else /* no TPROXY support */
6276 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006277 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006280#endif
6281 cur_arg += 2;
6282 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006283 }
6284
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006285 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6286#ifdef SO_BINDTODEVICE
6287 if (!*args[cur_arg + 1]) {
6288 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006290 err_code |= ERR_ALERT | ERR_FATAL;
6291 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006292 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006293 free(curproxy->conn_src.iface_name);
6294 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6295 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006296 global.last_checks |= LSTCHK_NETADM;
6297#else
6298 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6299 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006300 err_code |= ERR_ALERT | ERR_FATAL;
6301 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006302#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006303 cur_arg += 2;
6304 continue;
6305 }
6306 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006307 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006312 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6313 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6314 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006315 err_code |= ERR_ALERT | ERR_FATAL;
6316 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006319 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006320 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6321 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006322 err_code |= ERR_ALERT | ERR_FATAL;
6323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325
6326 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006327 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006328 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006329 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006331 }
6332 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006333 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006334 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006335 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006336 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338 }
6339 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006340 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006341 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006342 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006343 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 }
6346 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006347 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006348 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006349 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 }
6353 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006354 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006355 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006356 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006360 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006362 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006363 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006365 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006371 err_code |= ERR_ALERT | ERR_FATAL;
6372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374
6375 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006376 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006377 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
6381 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006383 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006384 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 }
6388 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006390 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006391 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006392 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 }
6395 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006396 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006397 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006398 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 }
6402 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006403 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006404 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006405 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006409 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006410 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006411 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006412 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006414 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006417 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006418
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 if (curproxy == &defproxy) {
6420 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006421 err_code |= ERR_ALERT | ERR_FATAL;
6422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006424 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006425 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 if (*(args[1]) == 0) {
6428 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006429 err_code |= ERR_ALERT | ERR_FATAL;
6430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006432
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006433 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006434 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006435 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6436 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006437 err_code |= ERR_ALERT | ERR_FATAL;
6438 goto out;
6439 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006440 err_code |= warnif_cond_conflicts(cond,
6441 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6442 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006443 }
6444 else if (*args[2]) {
6445 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6446 file, linenum, args[0], args[2]);
6447 err_code |= ERR_ALERT | ERR_FATAL;
6448 goto out;
6449 }
6450
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006451 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006452 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006453 wl->s = strdup(args[1]);
6454 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006455 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
6457 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006461 err_code |= ERR_ALERT | ERR_FATAL;
6462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006464
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006466 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006467 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006468 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 }
6471 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006472 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006473 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006474 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
6478 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006480 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006481 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006482 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
6485 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6488 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 }
6492
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006494 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006495 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 }
6499 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006501 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006502 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 }
6506 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006508 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006509 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 }
6513 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006514 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006515
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 if (curproxy == &defproxy) {
6517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006518 err_code |= ERR_ALERT | ERR_FATAL;
6519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006521 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006522 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524 if (*(args[1]) == 0) {
6525 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006526 err_code |= ERR_ALERT | ERR_FATAL;
6527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006528 }
6529
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006530 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006531 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006532 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6533 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006534 err_code |= ERR_ALERT | ERR_FATAL;
6535 goto out;
6536 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006537 err_code |= warnif_cond_conflicts(cond,
6538 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6539 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006540 }
6541 else if (*args[2]) {
6542 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6543 file, linenum, args[0], args[2]);
6544 err_code |= ERR_ALERT | ERR_FATAL;
6545 goto out;
6546 }
6547
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006548 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006549 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006550 wl->s = strdup(args[1]);
6551 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 }
6553 else if (!strcmp(args[0], "errorloc") ||
6554 !strcmp(args[0], "errorloc302") ||
6555 !strcmp(args[0], "errorloc303")) { /* error location */
6556 int errnum, errlen;
6557 char *err;
6558
Willy Tarreau977b8e42006-12-29 14:19:17 +01006559 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006560 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006561
Willy Tarreaubaaee002006-06-26 02:48:02 +02006562 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006563 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006564 err_code |= ERR_ALERT | ERR_FATAL;
6565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006566 }
6567
6568 errnum = atol(args[1]);
6569 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006570 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6571 err = malloc(errlen);
6572 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006573 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006574 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6575 err = malloc(errlen);
6576 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 }
6578
Willy Tarreau0f772532006-12-23 20:51:41 +01006579 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6580 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006581 chunk_destroy(&curproxy->errmsg[rc]);
6582 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006583 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006586
6587 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006588 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6589 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590 free(err);
6591 }
6592 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006593 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6594 int errnum, errlen, fd;
6595 char *err;
6596 struct stat stat;
6597
6598 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006599 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006600
6601 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006602 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006603 err_code |= ERR_ALERT | ERR_FATAL;
6604 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006605 }
6606
6607 fd = open(args[2], O_RDONLY);
6608 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6609 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6610 file, linenum, args[2], args[1]);
6611 if (fd >= 0)
6612 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006613 err_code |= ERR_ALERT | ERR_FATAL;
6614 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006615 }
6616
Willy Tarreau27a674e2009-08-17 07:23:33 +02006617 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006618 errlen = stat.st_size;
6619 } else {
6620 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006621 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006622 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006623 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006624 }
6625
6626 err = malloc(errlen); /* malloc() must succeed during parsing */
6627 errnum = read(fd, err, errlen);
6628 if (errnum != errlen) {
6629 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6630 file, linenum, args[2], args[1]);
6631 close(fd);
6632 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006633 err_code |= ERR_ALERT | ERR_FATAL;
6634 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006635 }
6636 close(fd);
6637
6638 errnum = atol(args[1]);
6639 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6640 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006641 chunk_destroy(&curproxy->errmsg[rc]);
6642 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006643 break;
6644 }
6645 }
6646
6647 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006648 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6649 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006650 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006651 free(err);
6652 }
6653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006654 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006655 struct cfg_kw_list *kwl;
6656 int index;
6657
6658 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6659 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6660 if (kwl->kw[index].section != CFG_LISTEN)
6661 continue;
6662 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6663 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006664 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006665 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006666 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006667 err_code |= ERR_ALERT | ERR_FATAL;
6668 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006669 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006670 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006671 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006672 err_code |= ERR_WARN;
6673 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006674 }
Willy Tarreau93893792009-07-23 13:19:11 +02006675 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006676 }
6677 }
6678 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006679
Willy Tarreau6daf3432008-01-22 16:44:08 +01006680 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006681 err_code |= ERR_ALERT | ERR_FATAL;
6682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006683 }
Willy Tarreau93893792009-07-23 13:19:11 +02006684 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006685 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006686 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006687}
6688
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006690cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6691{
6692#ifdef CONFIG_HAP_NS
6693 const char *err;
6694 const char *item = args[0];
6695
6696 if (!strcmp(item, "namespace_list")) {
6697 return 0;
6698 }
6699 else if (!strcmp(item, "namespace")) {
6700 size_t idx = 1;
6701 const char *current;
6702 while (*(current = args[idx++])) {
6703 err = invalid_char(current);
6704 if (err) {
6705 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6706 file, linenum, *err, item, current);
6707 return ERR_ALERT | ERR_FATAL;
6708 }
6709
6710 if (netns_store_lookup(current, strlen(current))) {
6711 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6712 file, linenum, current);
6713 return ERR_ALERT | ERR_FATAL;
6714 }
6715 if (!netns_store_insert(current)) {
6716 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6717 file, linenum, current);
6718 return ERR_ALERT | ERR_FATAL;
6719 }
6720 }
6721 }
6722
6723 return 0;
6724#else
6725 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6726 file, linenum);
6727 return ERR_ALERT | ERR_FATAL;
6728#endif
6729}
6730
6731int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6733{
6734
6735 int err_code = 0;
6736 const char *err;
6737
6738 if (!strcmp(args[0], "userlist")) { /* new userlist */
6739 struct userlist *newul;
6740
6741 if (!*args[1]) {
6742 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6743 file, linenum, args[0]);
6744 err_code |= ERR_ALERT | ERR_FATAL;
6745 goto out;
6746 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006747 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6748 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006749
6750 err = invalid_char(args[1]);
6751 if (err) {
6752 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6753 file, linenum, *err, args[0], args[1]);
6754 err_code |= ERR_ALERT | ERR_FATAL;
6755 goto out;
6756 }
6757
6758 for (newul = userlist; newul; newul = newul->next)
6759 if (!strcmp(newul->name, args[1])) {
6760 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6761 file, linenum, args[1]);
6762 err_code |= ERR_WARN;
6763 goto out;
6764 }
6765
Vincent Bernat02779b62016-04-03 13:48:43 +02006766 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006767 if (!newul) {
6768 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6769 err_code |= ERR_ALERT | ERR_ABORT;
6770 goto out;
6771 }
6772
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006773 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006774 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006775 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6776 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006777 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006778 goto out;
6779 }
6780
6781 newul->next = userlist;
6782 userlist = newul;
6783
6784 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006785 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006786 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006787 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006788
6789 if (!*args[1]) {
6790 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6791 file, linenum, args[0]);
6792 err_code |= ERR_ALERT | ERR_FATAL;
6793 goto out;
6794 }
6795
6796 err = invalid_char(args[1]);
6797 if (err) {
6798 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6799 file, linenum, *err, args[0], args[1]);
6800 err_code |= ERR_ALERT | ERR_FATAL;
6801 goto out;
6802 }
6803
William Lallemand4ac9f542015-05-28 18:03:51 +02006804 if (!userlist)
6805 goto out;
6806
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006807 for (ag = userlist->groups; ag; ag = ag->next)
6808 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006809 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6810 file, linenum, args[1], userlist->name);
6811 err_code |= ERR_ALERT;
6812 goto out;
6813 }
6814
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006815 ag = calloc(1, sizeof(*ag));
6816 if (!ag) {
6817 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6818 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006819 goto out;
6820 }
6821
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006822 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006823 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006824 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6825 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006826 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006827 goto out;
6828 }
6829
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006830 cur_arg = 2;
6831
6832 while (*args[cur_arg]) {
6833 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006834 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006835 cur_arg += 2;
6836 continue;
6837 } else {
6838 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6839 file, linenum, args[0]);
6840 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006841 free(ag->groupusers);
6842 free(ag->name);
6843 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006844 goto out;
6845 }
6846 }
6847
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006848 ag->next = userlist->groups;
6849 userlist->groups = ag;
6850
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006851 } else if (!strcmp(args[0], "user")) { /* new user */
6852 struct auth_users *newuser;
6853 int cur_arg;
6854
6855 if (!*args[1]) {
6856 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6857 file, linenum, args[0]);
6858 err_code |= ERR_ALERT | ERR_FATAL;
6859 goto out;
6860 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006861 if (!userlist)
6862 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006863
6864 for (newuser = userlist->users; newuser; newuser = newuser->next)
6865 if (!strcmp(newuser->user, args[1])) {
6866 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6867 file, linenum, args[1], userlist->name);
6868 err_code |= ERR_ALERT;
6869 goto out;
6870 }
6871
Vincent Bernat02779b62016-04-03 13:48:43 +02006872 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006873 if (!newuser) {
6874 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6875 err_code |= ERR_ALERT | ERR_ABORT;
6876 goto out;
6877 }
6878
6879 newuser->user = strdup(args[1]);
6880
6881 newuser->next = userlist->users;
6882 userlist->users = newuser;
6883
6884 cur_arg = 2;
6885
6886 while (*args[cur_arg]) {
6887 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006888#ifdef CONFIG_HAP_CRYPT
6889 if (!crypt("", args[cur_arg + 1])) {
6890 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6891 file, linenum, newuser->user);
6892 err_code |= ERR_ALERT | ERR_FATAL;
6893 goto out;
6894 }
6895#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006896 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6897 file, linenum);
6898 err_code |= ERR_ALERT;
6899#endif
6900 newuser->pass = strdup(args[cur_arg + 1]);
6901 cur_arg += 2;
6902 continue;
6903 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6904 newuser->pass = strdup(args[cur_arg + 1]);
6905 newuser->flags |= AU_O_INSECURE;
6906 cur_arg += 2;
6907 continue;
6908 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006909 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006910 cur_arg += 2;
6911 continue;
6912 } else {
6913 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6914 file, linenum, args[0]);
6915 err_code |= ERR_ALERT | ERR_FATAL;
6916 goto out;
6917 }
6918 }
6919 } else {
6920 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6921 err_code |= ERR_ALERT | ERR_FATAL;
6922 }
6923
6924out:
6925 return err_code;
6926}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006927
Christopher Faulet79bdef32016-11-04 22:36:15 +01006928int
6929cfg_parse_scope(const char *file, int linenum, char *line)
6930{
6931 char *beg, *end, *scope = NULL;
6932 int err_code = 0;
6933 const char *err;
6934
6935 beg = line + 1;
6936 end = strchr(beg, ']');
6937
6938 /* Detect end of scope declaration */
6939 if (!end || end == beg) {
6940 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6941 file, linenum);
6942 err_code |= ERR_ALERT | ERR_FATAL;
6943 goto out;
6944 }
6945
6946 /* Get scope name and check its validity */
6947 scope = my_strndup(beg, end-beg);
6948 err = invalid_char(scope);
6949 if (err) {
6950 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6951 file, linenum, *err);
6952 err_code |= ERR_ALERT | ERR_ABORT;
6953 goto out;
6954 }
6955
6956 /* Be sure to have a scope declaration alone on its line */
6957 line = end+1;
6958 while (isspace((unsigned char)*line))
6959 line++;
6960 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6961 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6962 file, linenum, *line);
6963 err_code |= ERR_ALERT | ERR_ABORT;
6964 goto out;
6965 }
6966
6967 /* We have a valid scope declaration, save it */
6968 free(cfg_scope);
6969 cfg_scope = scope;
6970 scope = NULL;
6971
6972 out:
6973 free(scope);
6974 return err_code;
6975}
6976
Willy Tarreaubaaee002006-06-26 02:48:02 +02006977/*
6978 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006979 * Returns the error code, 0 if OK, or any combination of :
6980 * - ERR_ABORT: must abort ASAP
6981 * - ERR_FATAL: we can continue parsing but not start the service
6982 * - ERR_WARN: a warning has been emitted
6983 * - ERR_ALERT: an alert has been emitted
6984 * Only the two first ones can stop processing, the two others are just
6985 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006986 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006987int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006988{
William Lallemand64e84512015-05-12 14:25:37 +02006989 char *thisline;
6990 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006991 FILE *f;
6992 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006993 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02006994 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006995 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006996 int readbytes = 0;
6997
6998 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006999 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007000 return -1;
7001 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007002
David Carlier97880bb2016-04-08 10:35:26 +01007003 if ((f=fopen(file,"r")) == NULL) {
7004 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007007
William Lallemandb2f07452015-05-12 14:27:13 +02007008next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007009 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007010 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007011 char *end;
7012 char *args[MAX_LINE_ARGS + 1];
7013 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007014 int dquote = 0; /* double quote */
7015 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007016
Willy Tarreaubaaee002006-06-26 02:48:02 +02007017 linenum++;
7018
7019 end = line + strlen(line);
7020
William Lallemand64e84512015-05-12 14:25:37 +02007021 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007022 /* Check if we reached the limit and the last char is not \n.
7023 * Watch out for the last line without the terminating '\n'!
7024 */
William Lallemand64e84512015-05-12 14:25:37 +02007025 char *newline;
7026 int newlinesize = linesize * 2;
7027
7028 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7029 if (newline == NULL) {
7030 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7031 file, linenum);
7032 err_code |= ERR_ALERT | ERR_FATAL;
7033 continue;
7034 }
7035
7036 readbytes = linesize - 1;
7037 linesize = newlinesize;
7038 thisline = newline;
7039 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007040 }
7041
William Lallemand64e84512015-05-12 14:25:37 +02007042 readbytes = 0;
7043
Willy Tarreaubaaee002006-06-26 02:48:02 +02007044 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007045 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007046 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007047
Christopher Faulet79bdef32016-11-04 22:36:15 +01007048
7049 if (*line == '[') {/* This is the begining if a scope */
7050 err_code |= cfg_parse_scope(file, linenum, line);
7051 goto next_line;
7052 }
7053
Willy Tarreaubaaee002006-06-26 02:48:02 +02007054 arg = 0;
7055 args[arg] = line;
7056
7057 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007058 if (*line == '"' && !squote) { /* double quote outside single quotes */
7059 if (dquote)
7060 dquote = 0;
7061 else
7062 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007063 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007064 end--;
7065 }
7066 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7067 if (squote)
7068 squote = 0;
7069 else
7070 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007071 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007072 end--;
7073 }
7074 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007075 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7076 * C equivalent value. Other combinations left unchanged (eg: \1).
7077 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007078 int skip = 0;
7079 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7080 *line = line[1];
7081 skip = 1;
7082 }
7083 else if (line[1] == 'r') {
7084 *line = '\r';
7085 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007087 else if (line[1] == 'n') {
7088 *line = '\n';
7089 skip = 1;
7090 }
7091 else if (line[1] == 't') {
7092 *line = '\t';
7093 skip = 1;
7094 }
7095 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007096 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007097 unsigned char hex1, hex2;
7098 hex1 = toupper(line[2]) - '0';
7099 hex2 = toupper(line[3]) - '0';
7100 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7101 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7102 *line = (hex1<<4) + hex2;
7103 skip = 3;
7104 }
7105 else {
7106 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007107 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007108 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007109 } else if (line[1] == '"') {
7110 *line = '"';
7111 skip = 1;
7112 } else if (line[1] == '\'') {
7113 *line = '\'';
7114 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007115 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7116 *line = '$';
7117 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007118 }
7119 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007120 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007121 end -= skip;
7122 }
7123 line++;
7124 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007125 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007126 /* end of string, end of loop */
7127 *line = 0;
7128 break;
7129 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007130 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007131 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007132 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007133 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007134 line++;
7135 args[++arg] = line;
7136 }
William Lallemandb2f07452015-05-12 14:27:13 +02007137 else if (dquote && *line == '$') {
7138 /* environment variables are evaluated inside double quotes */
7139 char *var_beg;
7140 char *var_end;
7141 char save_char;
7142 char *value;
7143 int val_len;
7144 int newlinesize;
7145 int braces = 0;
7146
7147 var_beg = line + 1;
7148 var_end = var_beg;
7149
7150 if (*var_beg == '{') {
7151 var_beg++;
7152 var_end++;
7153 braces = 1;
7154 }
7155
7156 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7157 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7158 err_code |= ERR_ALERT | ERR_FATAL;
7159 goto next_line; /* skip current line */
7160 }
7161
7162 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7163 var_end++;
7164
7165 save_char = *var_end;
7166 *var_end = '\0';
7167 value = getenv(var_beg);
7168 *var_end = save_char;
7169 val_len = value ? strlen(value) : 0;
7170
7171 if (braces) {
7172 if (*var_end == '}') {
7173 var_end++;
7174 braces = 0;
7175 } else {
7176 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7177 err_code |= ERR_ALERT | ERR_FATAL;
7178 goto next_line; /* skip current line */
7179 }
7180 }
7181
7182 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7183
7184 /* if not enough space in thisline */
7185 if (newlinesize > linesize) {
7186 char *newline;
7187
7188 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7189 if (newline == NULL) {
7190 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7191 err_code |= ERR_ALERT | ERR_FATAL;
7192 goto next_line; /* slip current line */
7193 }
7194 /* recompute pointers if realloc returns a new pointer */
7195 if (newline != thisline) {
7196 int i;
7197 int diff;
7198
7199 for (i = 0; i <= arg; i++) {
7200 diff = args[i] - thisline;
7201 args[i] = newline + diff;
7202 }
7203
7204 diff = var_end - thisline;
7205 var_end = newline + diff;
7206 diff = end - thisline;
7207 end = newline + diff;
7208 diff = line - thisline;
7209 line = newline + diff;
7210 thisline = newline;
7211 }
7212 linesize = newlinesize;
7213 }
7214
7215 /* insert value inside the line */
7216 memmove(line + val_len, var_end, end - var_end + 1);
7217 memcpy(line, value, val_len);
7218 end += val_len - (var_end - line);
7219 line += val_len;
7220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007221 else {
7222 line++;
7223 }
7224 }
William Lallemandb2f07452015-05-12 14:27:13 +02007225
William Lallemandf9873ba2015-05-05 17:37:14 +02007226 if (dquote) {
7227 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7228 err_code |= ERR_ALERT | ERR_FATAL;
7229 }
7230
7231 if (squote) {
7232 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7233 err_code |= ERR_ALERT | ERR_FATAL;
7234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007235
7236 /* empty line */
7237 if (!**args)
7238 continue;
7239
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007240 if (*line) {
7241 /* we had to stop due to too many args.
7242 * Let's terminate the string, print the offending part then cut the
7243 * last arg.
7244 */
7245 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7246 line++;
7247 *line = '\0';
7248
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007249 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007250 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007251 err_code |= ERR_ALERT | ERR_FATAL;
7252 args[arg] = line;
7253 }
7254
Willy Tarreau540abe42007-05-02 20:50:16 +02007255 /* zero out remaining args and ensure that at least one entry
7256 * is zeroed out.
7257 */
7258 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007259 args[arg] = line;
7260 }
7261
Willy Tarreau3842f002009-06-14 11:39:52 +02007262 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007263 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007264 char *tmp;
7265
Willy Tarreau3842f002009-06-14 11:39:52 +02007266 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007267 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007268 for (arg=0; *args[arg+1]; arg++)
7269 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007270 *tmp = '\0'; // fix the next arg to \0
7271 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007272 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007273 else if (!strcmp(args[0], "default")) {
7274 kwm = KWM_DEF;
7275 for (arg=0; *args[arg+1]; arg++)
7276 args[arg] = args[arg+1]; // shift args after inversion
7277 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007278
William Lallemand0f99e342011-10-12 17:50:54 +02007279 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7280 strcmp(args[0], "log") != 0) {
7281 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007282 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007283 }
7284
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007285 /* detect section start */
7286 list_for_each_entry(ics, &sections, list) {
7287 if (strcmp(args[0], ics->section_name) == 0) {
7288 cursection = ics->section_name;
7289 cs = ics;
7290 break;
7291 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007292 }
7293
William Lallemandd2ff56d2017-10-16 11:06:50 +02007294 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007295 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007296 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007297 } else {
7298 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007299
William Lallemandd2ff56d2017-10-16 11:06:50 +02007300 if (pcs != cs && pcs && pcs->post_section_parser) {
7301 err_code |= pcs->post_section_parser();
7302 if (err_code & ERR_ABORT)
7303 goto err;
7304 }
7305
7306 err_code |= cs->section_parser(file, linenum, args, kwm);
7307 if (err_code & ERR_ABORT)
7308 goto err;
7309 }
7310 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007311 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007312
7313 if (pcs == cs && pcs && pcs->post_section_parser)
7314 err_code |= pcs->post_section_parser();
7315
7316err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007317 free(cfg_scope);
7318 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007319 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007320 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007321 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007322 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007323}
7324
Willy Tarreau64ab6072014-09-16 12:17:36 +02007325/* This function propagates processes from frontend <from> to backend <to> so
7326 * that it is always guaranteed that a backend pointed to by a frontend is
7327 * bound to all of its processes. After that, if the target is a "listen"
7328 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007329 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007330 * checked first to ensure that <to> is already bound to all processes of
7331 * <from>, there is no risk of looping and we ensure to follow the shortest
7332 * path to the destination.
7333 *
7334 * It is possible to set <to> to NULL for the first call so that the function
7335 * takes care of visiting the initial frontend in <from>.
7336 *
7337 * It is important to note that the function relies on the fact that all names
7338 * have already been resolved.
7339 */
7340void propagate_processes(struct proxy *from, struct proxy *to)
7341{
7342 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007343
7344 if (to) {
7345 /* check whether we need to go down */
7346 if (from->bind_proc &&
7347 (from->bind_proc & to->bind_proc) == from->bind_proc)
7348 return;
7349
7350 if (!from->bind_proc && !to->bind_proc)
7351 return;
7352
7353 to->bind_proc = from->bind_proc ?
7354 (to->bind_proc | from->bind_proc) : 0;
7355
7356 /* now propagate down */
7357 from = to;
7358 }
7359
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007360 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007361 return;
7362
Willy Tarreauf6b70012014-12-18 14:00:43 +01007363 if (from->state == PR_STSTOPPED)
7364 return;
7365
Willy Tarreau64ab6072014-09-16 12:17:36 +02007366 /* default_backend */
7367 if (from->defbe.be)
7368 propagate_processes(from, from->defbe.be);
7369
7370 /* use_backend */
7371 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007372 if (rule->dynamic)
7373 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007374 to = rule->be.backend;
7375 propagate_processes(from, to);
7376 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007377}
7378
Willy Tarreaubb925012009-07-23 13:36:36 +02007379/*
7380 * Returns the error code, 0 if OK, or any combination of :
7381 * - ERR_ABORT: must abort ASAP
7382 * - ERR_FATAL: we can continue parsing but not start the service
7383 * - ERR_WARN: a warning has been emitted
7384 * - ERR_ALERT: an alert has been emitted
7385 * Only the two first ones can stop processing, the two others are just
7386 * indicators.
7387 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007388int check_config_validity()
7389{
7390 int cfgerr = 0;
7391 struct proxy *curproxy = NULL;
7392 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007393 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007394 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007395 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007396 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007397 struct dns_resolvers *curr_resolvers;
William Lallemand48b4bb42017-10-23 14:36:34 +02007398 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007399
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007400 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007401 /*
7402 * Now, check for the integrity of all that we have collected.
7403 */
7404
7405 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007406 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007407
Willy Tarreau193b8c62012-11-22 00:17:38 +01007408 if (!global.tune.max_http_hdr)
7409 global.tune.max_http_hdr = MAX_HTTP_HDR;
7410
7411 if (!global.tune.cookie_len)
7412 global.tune.cookie_len = CAPTURE_LEN;
7413
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007414 if (!global.tune.requri_len)
7415 global.tune.requri_len = REQURI_LEN;
7416
Emeric Brun96fd9262017-07-05 13:33:16 +02007417 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7418
Willy Tarreau193b8c62012-11-22 00:17:38 +01007419 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7420
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007421 /* allocate pool of resolution per resolvers */
7422 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7423 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7424 /* error message is already displayed by dns_alloc_resolution_pool() */
7425 err_code |= ERR_ALERT | ERR_ABORT;
7426 goto out;
7427 }
7428 }
7429
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007430 /* Post initialisation of the users and groups lists. */
7431 err_code = userlist_postinit();
7432 if (err_code != ERR_NONE)
7433 goto out;
7434
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007435 /* first, we will invert the proxy list order */
7436 curproxy = NULL;
7437 while (proxy) {
7438 struct proxy *next;
7439
7440 next = proxy->next;
7441 proxy->next = curproxy;
7442 curproxy = proxy;
7443 if (!next)
7444 break;
7445 proxy = next;
7446 }
7447
Willy Tarreau419ead82014-09-16 13:41:21 +02007448 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007449 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007450 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007451 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007452 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007453 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007454 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007455 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007456
Willy Tarreau050536d2012-10-04 08:47:34 +02007457 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007458 /* proxy ID not set, use automatic numbering with first
7459 * spare entry starting with next_pxid.
7460 */
7461 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7462 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7463 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007464 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007465 next_pxid++;
7466
Willy Tarreau55ea7572007-06-17 19:56:27 +02007467
Willy Tarreaubaaee002006-06-26 02:48:02 +02007468 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007469 /* ensure we don't keep listeners uselessly bound */
7470 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007471 free((void *)curproxy->table.peers.name);
7472 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007473 continue;
7474 }
7475
Willy Tarreau102df612014-05-07 23:56:38 +02007476 /* Check multi-process mode compatibility for the current proxy */
7477
7478 if (curproxy->bind_proc) {
7479 /* an explicit bind-process was specified, let's check how many
7480 * processes remain.
7481 */
David Carliere6c39412015-07-02 07:00:17 +00007482 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007483
7484 curproxy->bind_proc &= nbits(global.nbproc);
7485 if (!curproxy->bind_proc && nbproc == 1) {
7486 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);
7487 curproxy->bind_proc = 1;
7488 }
7489 else if (!curproxy->bind_proc && nbproc > 1) {
7490 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);
7491 curproxy->bind_proc = 0;
7492 }
7493 }
7494
Willy Tarreau3d209582014-05-09 17:06:11 +02007495 /* check and reduce the bind-proc of each listener */
7496 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7497 unsigned long mask;
7498
7499 if (!bind_conf->bind_proc)
7500 continue;
7501
7502 mask = nbits(global.nbproc);
7503 if (curproxy->bind_proc)
7504 mask &= curproxy->bind_proc;
7505 /* mask cannot be null here thanks to the previous checks */
7506
David Carliere6c39412015-07-02 07:00:17 +00007507 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007508 bind_conf->bind_proc &= mask;
7509
7510 if (!bind_conf->bind_proc && nbproc == 1) {
7511 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",
7512 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7513 bind_conf->bind_proc = mask & ~(mask - 1);
7514 }
7515 else if (!bind_conf->bind_proc && nbproc > 1) {
7516 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",
7517 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7518 bind_conf->bind_proc = 0;
7519 }
7520 }
7521
Willy Tarreauff01a212009-03-15 13:46:16 +01007522 switch (curproxy->mode) {
7523 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007524 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007525 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007526 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7527 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007528 cfgerr++;
7529 }
7530
7531 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007532 Warning("config : servers will be ignored for %s '%s'.\n",
7533 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007534 break;
7535
7536 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007537 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007538 break;
7539
7540 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007541 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007542 break;
7543 }
7544
Willy Tarreauf3934b82015-08-11 11:36:45 +02007545 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7546 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7547 proxy_type_str(curproxy), curproxy->id);
7548 err_code |= ERR_WARN;
7549 }
7550
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007551 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007552 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007553 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007554 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7555 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007556 cfgerr++;
7557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007558#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007559 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007560 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7561 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007562 cfgerr++;
7563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007564#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007565 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007566 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7567 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007568 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007569 }
7570 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007571 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007572 /* If no LB algo is set in a backend, and we're not in
7573 * transparent mode, dispatch mode nor proxy mode, we
7574 * want to use balance roundrobin by default.
7575 */
7576 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7577 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007578 }
7579 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007580
Willy Tarreau1620ec32011-08-06 17:05:02 +02007581 if (curproxy->options & PR_O_DISPATCH)
7582 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7583 else if (curproxy->options & PR_O_HTTP_PROXY)
7584 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7585 else if (curproxy->options & PR_O_TRANSP)
7586 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007587
Willy Tarreau1620ec32011-08-06 17:05:02 +02007588 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7589 if (curproxy->options & PR_O_DISABLE404) {
7590 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7591 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7592 err_code |= ERR_WARN;
7593 curproxy->options &= ~PR_O_DISABLE404;
7594 }
7595 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7596 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7597 "send-state", proxy_type_str(curproxy), curproxy->id);
7598 err_code |= ERR_WARN;
7599 curproxy->options &= ~PR_O2_CHK_SNDST;
7600 }
Willy Tarreauef781042010-01-27 11:53:01 +01007601 }
7602
Simon Horman98637e52014-06-20 12:30:16 +09007603 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7604 if (!global.external_check) {
7605 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7606 curproxy->id, "option external-check");
7607 cfgerr++;
7608 }
7609 if (!curproxy->check_command) {
7610 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7611 curproxy->id, "option external-check");
7612 cfgerr++;
7613 }
7614 }
7615
Simon Horman64e34162015-02-06 11:11:57 +09007616 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007617 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7618 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007619 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7620 "'email-alert myhostname', or 'email-alert to' "
7621 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007622 "to be present).\n",
7623 proxy_type_str(curproxy), curproxy->id);
7624 err_code |= ERR_WARN;
7625 free_email_alert(curproxy);
7626 }
7627 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007628 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007629 }
7630
Simon Horman98637e52014-06-20 12:30:16 +09007631 if (curproxy->check_command) {
7632 int clear = 0;
7633 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7634 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7635 "external-check command", proxy_type_str(curproxy), curproxy->id);
7636 err_code |= ERR_WARN;
7637 clear = 1;
7638 }
7639 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007640 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007641 curproxy->id, "external-check command");
7642 cfgerr++;
7643 }
7644 if (clear) {
7645 free(curproxy->check_command);
7646 curproxy->check_command = NULL;
7647 }
7648 }
7649
7650 if (curproxy->check_path) {
7651 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7652 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7653 "external-check path", proxy_type_str(curproxy), curproxy->id);
7654 err_code |= ERR_WARN;
7655 free(curproxy->check_path);
7656 curproxy->check_path = NULL;
7657 }
7658 }
7659
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007660 /* if a default backend was specified, let's find it */
7661 if (curproxy->defbe.name) {
7662 struct proxy *target;
7663
Willy Tarreauafb39922015-05-26 12:04:09 +02007664 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007665 if (!target) {
7666 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7667 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007668 cfgerr++;
7669 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007670 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7671 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007672 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007673 } else if (target->mode != curproxy->mode &&
7674 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7675
7676 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7677 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7678 curproxy->conf.file, curproxy->conf.line,
7679 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7680 target->conf.file, target->conf.line);
7681 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007682 } else {
7683 free(curproxy->defbe.name);
7684 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007685 /* Update tot_fe_maxconn for a further fullconn's computation */
7686 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007687 /* Emit a warning if this proxy also has some servers */
7688 if (curproxy->srv) {
7689 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7690 curproxy->id);
7691 err_code |= ERR_WARN;
7692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007693 }
7694 }
7695
Emeric Brun3f783572017-01-12 11:21:28 +01007696 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7697 /* Case of listen without default backend
7698 * The curproxy will be its own default backend
7699 * so we update tot_fe_maxconn for a further
7700 * fullconn's computation */
7701 curproxy->tot_fe_maxconn += curproxy->maxconn;
7702 }
7703
Willy Tarreau55ea7572007-06-17 19:56:27 +02007704 /* find the target proxy for 'use_backend' rules */
7705 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007706 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007707 struct logformat_node *node;
7708 char *pxname;
7709
7710 /* Try to parse the string as a log format expression. If the result
7711 * of the parsing is only one entry containing a simple string, then
7712 * it's a standard string corresponding to a static rule, thus the
7713 * parsing is cancelled and be.name is restored to be resolved.
7714 */
7715 pxname = rule->be.name;
7716 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007717 curproxy->conf.args.ctx = ARGC_UBK;
7718 curproxy->conf.args.file = rule->file;
7719 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007720 err = NULL;
7721 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7722 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7723 rule->file, rule->line, pxname, err);
7724 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007725 cfgerr++;
7726 continue;
7727 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007728 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7729
7730 if (!LIST_ISEMPTY(&rule->be.expr)) {
7731 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7732 rule->dynamic = 1;
7733 free(pxname);
7734 continue;
7735 }
7736 /* simple string: free the expression and fall back to static rule */
7737 free(node->arg);
7738 free(node);
7739 }
7740
7741 rule->dynamic = 0;
7742 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007743
Willy Tarreauafb39922015-05-26 12:04:09 +02007744 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007745 if (!target) {
7746 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7747 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007748 cfgerr++;
7749 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007750 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7751 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007752 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007753 } else if (target->mode != curproxy->mode &&
7754 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7755
7756 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7757 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7758 curproxy->conf.file, curproxy->conf.line,
7759 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7760 target->conf.file, target->conf.line);
7761 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007762 } else {
7763 free((void *)rule->be.name);
7764 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007765 /* For each target of switching rules, we update
7766 * their tot_fe_maxconn, except if a previous rule point
7767 * on the same backend or on the default backend */
7768 if (rule->be.backend != curproxy->defbe.be) {
7769 struct switching_rule *swrule;
7770
7771 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7772 if (rule == swrule) {
7773 target->tot_fe_maxconn += curproxy->maxconn;
7774 break;
7775 }
7776 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7777 /* there is multiple ref of this backend */
7778 break;
7779 }
7780 }
7781 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007782 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007783 }
7784
Willy Tarreau64ab6072014-09-16 12:17:36 +02007785 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007786 list_for_each_entry(srule, &curproxy->server_rules, list) {
7787 struct server *target = findserver(curproxy, srule->srv.name);
7788
7789 if (!target) {
7790 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7791 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7792 cfgerr++;
7793 continue;
7794 }
7795 free((void *)srule->srv.name);
7796 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007797 }
7798
Emeric Brunb982a3d2010-01-04 15:45:53 +01007799 /* find the target table for 'stick' rules */
7800 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7801 struct proxy *target;
7802
Emeric Brun1d33b292010-01-04 15:47:17 +01007803 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7804 if (mrule->flags & STK_IS_STORE)
7805 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7806
Emeric Brunb982a3d2010-01-04 15:45:53 +01007807 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007808 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007809 else
7810 target = curproxy;
7811
7812 if (!target) {
7813 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7814 curproxy->id, mrule->table.name);
7815 cfgerr++;
7816 }
7817 else if (target->table.size == 0) {
7818 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7819 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7820 cfgerr++;
7821 }
Willy Tarreau12785782012-04-27 21:37:17 +02007822 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7823 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007824 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7825 cfgerr++;
7826 }
7827 else {
7828 free((void *)mrule->table.name);
7829 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007830 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007831 }
7832 }
7833
7834 /* find the target table for 'store response' rules */
7835 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7836 struct proxy *target;
7837
Emeric Brun1d33b292010-01-04 15:47:17 +01007838 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7839
Emeric Brunb982a3d2010-01-04 15:45:53 +01007840 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007841 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007842 else
7843 target = curproxy;
7844
7845 if (!target) {
7846 Alert("Proxy '%s': unable to find store table '%s'.\n",
7847 curproxy->id, mrule->table.name);
7848 cfgerr++;
7849 }
7850 else if (target->table.size == 0) {
7851 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7852 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7853 cfgerr++;
7854 }
Willy Tarreau12785782012-04-27 21:37:17 +02007855 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7856 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007857 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7858 cfgerr++;
7859 }
7860 else {
7861 free((void *)mrule->table.name);
7862 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007863 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007864 }
7865 }
7866
Christopher Faulete4e830d2017-09-18 14:51:41 +02007867 /* check validity for 'tcp-request' layer 4 rules */
7868 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
7869 err = NULL;
7870 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7871 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7872 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01007873 cfgerr++;
7874 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007875 }
7876
Christopher Faulete4e830d2017-09-18 14:51:41 +02007877 /* check validity for 'tcp-request' layer 5 rules */
7878 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
7879 err = NULL;
7880 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7881 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7882 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007883 cfgerr++;
7884 }
7885 }
7886
Christopher Faulete4e830d2017-09-18 14:51:41 +02007887 /* check validity for 'tcp-request' layer 6 rules */
7888 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
7889 err = NULL;
7890 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7891 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7892 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007893 cfgerr++;
7894 }
7895 }
7896
Christopher Faulete4e830d2017-09-18 14:51:41 +02007897 /* check validity for 'http-request' layer 7 rules */
7898 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
7899 err = NULL;
7900 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7901 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7902 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007903 cfgerr++;
7904 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007905 }
7906
Christopher Faulete4e830d2017-09-18 14:51:41 +02007907 /* check validity for 'http-response' layer 7 rules */
7908 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
7909 err = NULL;
7910 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7911 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7912 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02007913 cfgerr++;
7914 }
Willy Tarreau09448f72014-06-25 18:12:15 +02007915 }
7916
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007917 /* move any "block" rules at the beginning of the http-request rules */
7918 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7919 /* insert block_rules into http_req_rules at the beginning */
7920 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7921 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7922 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7923 curproxy->http_req_rules.n = curproxy->block_rules.n;
7924 LIST_INIT(&curproxy->block_rules);
7925 }
7926
Emeric Brun32da3c42010-09-23 18:39:19 +02007927 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007928 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007929
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007930 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02007931 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7932 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007933 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007934 break;
7935 }
7936 }
7937
7938 if (!curpeers) {
7939 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7940 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007941 free((void *)curproxy->table.peers.name);
7942 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007943 cfgerr++;
7944 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007945 else if (curpeers->state == PR_STSTOPPED) {
7946 /* silently disable this peers section */
7947 curproxy->table.peers.p = NULL;
7948 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007949 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007950 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7951 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007952 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007953 cfgerr++;
7954 }
7955 }
7956
Simon Horman9dc49962015-01-30 11:22:59 +09007957
7958 if (curproxy->email_alert.mailers.name) {
7959 struct mailers *curmailers = mailers;
7960
7961 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7962 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7963 free(curproxy->email_alert.mailers.name);
7964 curproxy->email_alert.mailers.m = curmailers;
7965 curmailers->users++;
7966 break;
7967 }
7968 }
7969
7970 if (!curmailers) {
7971 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7972 curproxy->id, curproxy->email_alert.mailers.name);
7973 free_email_alert(curproxy);
7974 cfgerr++;
7975 }
7976 }
7977
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007978 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007979 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007980 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7981 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7982 "proxy", curproxy->id);
7983 cfgerr++;
7984 goto out_uri_auth_compat;
7985 }
7986
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007987 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007988 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007989 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007990 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007991
Willy Tarreau95fa4692010-02-01 13:05:50 +01007992 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7993 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007994
7995 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007996 uri_auth_compat_req[i++] = "realm";
7997 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7998 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007999
Willy Tarreau95fa4692010-02-01 13:05:50 +01008000 uri_auth_compat_req[i++] = "unless";
8001 uri_auth_compat_req[i++] = "{";
8002 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8003 uri_auth_compat_req[i++] = "}";
8004 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008005
Willy Tarreauff011f22011-01-06 17:51:27 +01008006 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8007 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008008 cfgerr++;
8009 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008010 }
8011
Willy Tarreauff011f22011-01-06 17:51:27 +01008012 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008013
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008014 if (curproxy->uri_auth->auth_realm) {
8015 free(curproxy->uri_auth->auth_realm);
8016 curproxy->uri_auth->auth_realm = NULL;
8017 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008018
8019 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008020 }
8021out_uri_auth_compat:
8022
Dragan Dosen43885c72015-10-01 13:18:13 +02008023 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008024 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008025 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8026 if (!curproxy->conf.logformat_sd_string) {
8027 /* set the default logformat_sd_string */
8028 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8029 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008030 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008031 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008032 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008033
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008034 /* compile the log format */
8035 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008036 if (curproxy->conf.logformat_string != default_http_log_format &&
8037 curproxy->conf.logformat_string != default_tcp_log_format &&
8038 curproxy->conf.logformat_string != clf_http_log_format)
8039 free(curproxy->conf.logformat_string);
8040 curproxy->conf.logformat_string = NULL;
8041 free(curproxy->conf.lfs_file);
8042 curproxy->conf.lfs_file = NULL;
8043 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008044
8045 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8046 free(curproxy->conf.logformat_sd_string);
8047 curproxy->conf.logformat_sd_string = NULL;
8048 free(curproxy->conf.lfsd_file);
8049 curproxy->conf.lfsd_file = NULL;
8050 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008051 }
8052
Willy Tarreau62a61232013-04-12 18:13:46 +02008053 if (curproxy->conf.logformat_string) {
8054 curproxy->conf.args.ctx = ARGC_LOG;
8055 curproxy->conf.args.file = curproxy->conf.lfs_file;
8056 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008057 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008058 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008059 SMP_VAL_FE_LOG_END, &err)) {
8060 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8061 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8062 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008063 cfgerr++;
8064 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008065 curproxy->conf.args.file = NULL;
8066 curproxy->conf.args.line = 0;
8067 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008068
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008069 if (curproxy->conf.logformat_sd_string) {
8070 curproxy->conf.args.ctx = ARGC_LOGSD;
8071 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8072 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008073 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008074 if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008075 SMP_VAL_FE_LOG_END, &err)) {
8076 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8077 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8078 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008079 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008080 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8081 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8082 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8083 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008084 cfgerr++;
8085 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008086 curproxy->conf.args.file = NULL;
8087 curproxy->conf.args.line = 0;
8088 }
8089
Willy Tarreau62a61232013-04-12 18:13:46 +02008090 if (curproxy->conf.uniqueid_format_string) {
8091 curproxy->conf.args.ctx = ARGC_UIF;
8092 curproxy->conf.args.file = curproxy->conf.uif_file;
8093 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008094 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008095 if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008096 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8097 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8098 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8099 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008100 cfgerr++;
8101 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008102 curproxy->conf.args.file = NULL;
8103 curproxy->conf.args.line = 0;
8104 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008105
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008106 /* only now we can check if some args remain unresolved.
8107 * This must be done after the users and groups resolution.
8108 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008109 cfgerr += smp_resolve_args(curproxy);
8110 if (!cfgerr)
8111 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008112
Willy Tarreau2738a142006-07-08 17:28:09 +02008113 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008114 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008115 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008116 (!curproxy->timeout.connect ||
8117 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008118 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008119 " | While not properly invalid, you will certainly encounter various problems\n"
8120 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008121 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008122 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008123 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008124 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008125
Willy Tarreau1fa31262007-12-03 00:36:16 +01008126 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8127 * We must still support older configurations, so let's find out whether those
8128 * parameters have been set or must be copied from contimeouts.
8129 */
8130 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008131 if (!curproxy->timeout.tarpit ||
8132 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008133 /* tarpit timeout not set. We search in the following order:
8134 * default.tarpit, curr.connect, default.connect.
8135 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008136 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008137 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008138 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008139 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008140 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008141 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008142 }
8143 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008144 (!curproxy->timeout.queue ||
8145 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008146 /* queue timeout not set. We search in the following order:
8147 * default.queue, curr.connect, default.connect.
8148 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008149 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008150 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008151 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008152 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008153 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008154 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008155 }
8156 }
8157
Willy Tarreau1620ec32011-08-06 17:05:02 +02008158 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008159 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008160 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008161 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008162 }
8163
Willy Tarreau215663d2014-06-13 18:30:23 +02008164 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8165 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8166 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8167 proxy_type_str(curproxy), curproxy->id);
8168 err_code |= ERR_WARN;
8169 }
8170
Willy Tarreau193b8c62012-11-22 00:17:38 +01008171 /* ensure that cookie capture length is not too large */
8172 if (curproxy->capture_len >= global.tune.cookie_len) {
8173 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8174 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8175 err_code |= ERR_WARN;
8176 curproxy->capture_len = global.tune.cookie_len - 1;
8177 }
8178
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008179 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008180 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008181 curproxy->req_cap_pool = create_pool("ptrcap",
8182 curproxy->nb_req_cap * sizeof(char *),
8183 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008184 }
8185
8186 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008187 curproxy->rsp_cap_pool = create_pool("ptrcap",
8188 curproxy->nb_rsp_cap * sizeof(char *),
8189 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008190 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008191
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008192 switch (curproxy->load_server_state_from_file) {
8193 case PR_SRV_STATE_FILE_UNSPEC:
8194 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8195 break;
8196 case PR_SRV_STATE_FILE_GLOBAL:
8197 if (!global.server_state_file) {
8198 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",
8199 curproxy->id);
8200 err_code |= ERR_WARN;
8201 }
8202 break;
8203 }
8204
Willy Tarreaubaaee002006-06-26 02:48:02 +02008205 /* first, we will invert the servers list order */
8206 newsrv = NULL;
8207 while (curproxy->srv) {
8208 struct server *next;
8209
8210 next = curproxy->srv->next;
8211 curproxy->srv->next = newsrv;
8212 newsrv = curproxy->srv;
8213 if (!next)
8214 break;
8215 curproxy->srv = next;
8216 }
8217
Willy Tarreau17edc812014-01-03 12:14:34 +01008218 /* Check that no server name conflicts. This causes trouble in the stats.
8219 * We only emit a warning for the first conflict affecting each server,
8220 * in order to avoid combinatory explosion if all servers have the same
8221 * name. We do that only for servers which do not have an explicit ID,
8222 * because these IDs were made also for distinguishing them and we don't
8223 * want to annoy people who correctly manage them.
8224 */
8225 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8226 struct server *other_srv;
8227
8228 if (newsrv->puid)
8229 continue;
8230
8231 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8232 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8233 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8234 newsrv->conf.file, newsrv->conf.line,
8235 proxy_type_str(curproxy), curproxy->id,
8236 newsrv->id, other_srv->conf.line);
8237 break;
8238 }
8239 }
8240 }
8241
Willy Tarreaudd701652010-05-25 23:03:02 +02008242 /* assign automatic UIDs to servers which don't have one yet */
8243 next_id = 1;
8244 newsrv = curproxy->srv;
8245 while (newsrv != NULL) {
8246 if (!newsrv->puid) {
8247 /* server ID not set, use automatic numbering with first
8248 * spare entry starting with next_svid.
8249 */
8250 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8251 newsrv->conf.id.key = newsrv->puid = next_id;
8252 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8253 }
8254 next_id++;
8255 newsrv = newsrv->next;
8256 }
8257
Willy Tarreau20697042007-11-15 23:26:18 +01008258 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008259 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008260
Willy Tarreau62c3be22012-01-20 13:12:32 +01008261 /*
8262 * If this server supports a maxconn parameter, it needs a dedicated
8263 * tasks to fill the emptied slots when a connection leaves.
8264 * Also, resolve deferred tracking dependency if needed.
8265 */
8266 newsrv = curproxy->srv;
8267 while (newsrv != NULL) {
8268 if (newsrv->minconn > newsrv->maxconn) {
8269 /* Only 'minconn' was specified, or it was higher than or equal
8270 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8271 * this will avoid further useless expensive computations.
8272 */
8273 newsrv->maxconn = newsrv->minconn;
8274 } else if (newsrv->maxconn && !newsrv->minconn) {
8275 /* minconn was not specified, so we set it to maxconn */
8276 newsrv->minconn = newsrv->maxconn;
8277 }
8278
Willy Tarreau17d45382016-12-22 21:16:08 +01008279 /* this will also properly set the transport layer for prod and checks */
8280 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8281 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8282 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8283 }
Emeric Brun94324a42012-10-11 14:00:19 +02008284
Willy Tarreau2f075e92013-12-03 11:11:34 +01008285 /* set the check type on the server */
8286 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8287
Willy Tarreau62c3be22012-01-20 13:12:32 +01008288 if (newsrv->trackit) {
8289 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008290 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008291 char *pname, *sname;
8292
8293 pname = newsrv->trackit;
8294 sname = strrchr(pname, '/');
8295
8296 if (sname)
8297 *sname++ = '\0';
8298 else {
8299 sname = pname;
8300 pname = NULL;
8301 }
8302
8303 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008304 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008305 if (!px) {
8306 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8307 proxy_type_str(curproxy), curproxy->id,
8308 newsrv->id, pname);
8309 cfgerr++;
8310 goto next_srv;
8311 }
8312 } else
8313 px = curproxy;
8314
8315 srv = findserver(px, sname);
8316 if (!srv) {
8317 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8318 proxy_type_str(curproxy), curproxy->id,
8319 newsrv->id, sname);
8320 cfgerr++;
8321 goto next_srv;
8322 }
8323
Willy Tarreau32091232014-05-16 13:52:00 +02008324 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8325 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8326 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008327 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008328 "tracking as it does not have any check nor agent enabled.\n",
8329 proxy_type_str(curproxy), curproxy->id,
8330 newsrv->id, px->id, srv->id);
8331 cfgerr++;
8332 goto next_srv;
8333 }
8334
8335 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8336
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008337 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008338 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8339 "belongs to a tracking chain looping back to %s/%s.\n",
8340 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008341 newsrv->id, px->id, srv->id, px->id,
8342 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008343 cfgerr++;
8344 goto next_srv;
8345 }
8346
8347 if (curproxy != px &&
8348 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8349 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8350 "tracking: disable-on-404 option inconsistency.\n",
8351 proxy_type_str(curproxy), curproxy->id,
8352 newsrv->id, px->id, srv->id);
8353 cfgerr++;
8354 goto next_srv;
8355 }
8356
Willy Tarreau62c3be22012-01-20 13:12:32 +01008357 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008358 newsrv->tracknext = srv->trackers;
8359 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008360
8361 free(newsrv->trackit);
8362 newsrv->trackit = NULL;
8363 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008364
8365 /*
8366 * resolve server's resolvers name and update the resolvers pointer
8367 * accordingly
8368 */
8369 if (newsrv->resolvers_id) {
8370 struct dns_resolvers *curr_resolvers;
8371 int found;
8372
8373 found = 0;
8374 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8375 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8376 found = 1;
8377 break;
8378 }
8379 }
8380
8381 if (!found) {
8382 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8383 proxy_type_str(curproxy), curproxy->id,
8384 newsrv->id, newsrv->resolvers_id);
8385 cfgerr++;
8386 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008387 if (newsrv->srvrq) {
8388 if (!newsrv->srvrq->resolvers) {
8389 newsrv->srvrq->resolvers = curr_resolvers;
8390 if (dns_link_resolution(newsrv->srvrq,
8391 OBJ_TYPE_SRVRQ, NULL) != 0) {
8392 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8393 proxy_type_str(curproxy), curproxy->id,
8394 newsrv->id);
8395 cfgerr++;
8396 }
8397 }
8398
8399 }
8400 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008401 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008402 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8403 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8404 proxy_type_str(curproxy), curproxy->id,
8405 newsrv->id);
8406 cfgerr++;
8407 }
8408 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008409 }
8410 }
8411 else {
8412 /* if no resolvers section associated to this server
8413 * we can clean up the associated resolution structure
8414 */
8415 if (newsrv->resolution) {
8416 free(newsrv->resolution->hostname_dn);
8417 newsrv->resolution->hostname_dn = NULL;
8418 free(newsrv->resolution);
8419 newsrv->resolution = NULL;
8420 }
8421 }
8422
Willy Tarreau62c3be22012-01-20 13:12:32 +01008423 next_srv:
8424 newsrv = newsrv->next;
8425 }
8426
Olivier Houchard4e694042017-03-14 20:01:29 +01008427 /*
8428 * Try to generate dynamic cookies for servers now.
8429 * It couldn't be done earlier, since at the time we parsed
8430 * the server line, we may not have known yet that we
8431 * should use dynamic cookies, or the secret key may not
8432 * have been provided yet.
8433 */
8434 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8435 newsrv = curproxy->srv;
8436 while (newsrv != NULL) {
8437 srv_set_dyncookie(newsrv);
8438 newsrv = newsrv->next;
8439 }
8440
8441 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008442 /* We have to initialize the server lookup mechanism depending
8443 * on what LB algorithm was choosen.
8444 */
8445
8446 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8447 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8448 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008449 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8450 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8451 init_server_map(curproxy);
8452 } else {
8453 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8454 fwrr_init_server_groups(curproxy);
8455 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008456 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008457
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008458 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008459 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8460 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8461 fwlc_init_server_tree(curproxy);
8462 } else {
8463 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8464 fas_init_server_tree(curproxy);
8465 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008466 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008467
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008468 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008469 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8470 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8471 chash_init_server_tree(curproxy);
8472 } else {
8473 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8474 init_server_map(curproxy);
8475 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008476 break;
8477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008478
8479 if (curproxy->options & PR_O_LOGASAP)
8480 curproxy->to_log &= ~LW_BYTES;
8481
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008482 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008483 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8484 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008485 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8486 proxy_type_str(curproxy), curproxy->id);
8487 err_code |= ERR_WARN;
8488 }
8489
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008490 if (curproxy->mode != PR_MODE_HTTP) {
8491 int optnum;
8492
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008493 if (curproxy->uri_auth) {
8494 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8495 proxy_type_str(curproxy), curproxy->id);
8496 err_code |= ERR_WARN;
8497 curproxy->uri_auth = NULL;
8498 }
8499
Willy Tarreaude7dc882017-03-10 11:49:21 +01008500 if (curproxy->capture_name) {
8501 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8502 proxy_type_str(curproxy), curproxy->id);
8503 err_code |= ERR_WARN;
8504 }
8505
8506 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8507 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8508 proxy_type_str(curproxy), curproxy->id);
8509 err_code |= ERR_WARN;
8510 }
8511
8512 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8513 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8514 proxy_type_str(curproxy), curproxy->id);
8515 err_code |= ERR_WARN;
8516 }
8517
8518 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8519 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8520 proxy_type_str(curproxy), curproxy->id);
8521 err_code |= ERR_WARN;
8522 }
8523
8524 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8525 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8526 proxy_type_str(curproxy), curproxy->id);
8527 err_code |= ERR_WARN;
8528 }
8529
Willy Tarreau87cf5142011-08-19 22:57:24 +02008530 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008531 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8532 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8533 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008534 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008535 }
8536
8537 if (curproxy->options & PR_O_ORGTO) {
8538 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8539 "originalto", proxy_type_str(curproxy), curproxy->id);
8540 err_code |= ERR_WARN;
8541 curproxy->options &= ~PR_O_ORGTO;
8542 }
8543
8544 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8545 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8546 (curproxy->cap & cfg_opts[optnum].cap) &&
8547 (curproxy->options & cfg_opts[optnum].val)) {
8548 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8549 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8550 err_code |= ERR_WARN;
8551 curproxy->options &= ~cfg_opts[optnum].val;
8552 }
8553 }
8554
8555 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8556 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8557 (curproxy->cap & cfg_opts2[optnum].cap) &&
8558 (curproxy->options2 & cfg_opts2[optnum].val)) {
8559 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8560 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8561 err_code |= ERR_WARN;
8562 curproxy->options2 &= ~cfg_opts2[optnum].val;
8563 }
8564 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008565
Willy Tarreau29fbe512015-08-20 19:35:14 +02008566#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008567 if (curproxy->conn_src.bind_hdr_occ) {
8568 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008569 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008570 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008571 err_code |= ERR_WARN;
8572 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008573#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008574 }
8575
Willy Tarreaubaaee002006-06-26 02:48:02 +02008576 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008577 * ensure that we're not cross-dressing a TCP server into HTTP.
8578 */
8579 newsrv = curproxy->srv;
8580 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008581 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008582 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8583 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008584 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008585 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008586
Willy Tarreau0cec3312011-10-31 13:49:26 +01008587 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8588 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8589 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8590 err_code |= ERR_WARN;
8591 }
8592
Willy Tarreauc93cd162014-05-13 15:54:22 +02008593 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008594 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8595 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8596 err_code |= ERR_WARN;
8597 }
8598
Willy Tarreau29fbe512015-08-20 19:35:14 +02008599#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008600 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8601 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008602 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 +01008603 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008604 err_code |= ERR_WARN;
8605 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008606#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008607
8608 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8609 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8610 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8611 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8612 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8613 Warning("config : %s '%s' : connections to server '%s' use the client's IP address as the source while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'usesrc' and to use the 'forwardfor' option instead.\n",
8614 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8615 err_code |= ERR_WARN;
8616 }
8617
8618
8619 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8620 Warning("config : %s '%s' : connections to server '%s' will have a PROXY protocol header announcing the first client's IP address while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'send-proxy' and to use the 'forwardfor' option instead.\n",
8621 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8622 err_code |= ERR_WARN;
8623 }
8624 }
8625
Willy Tarreau21d2af32008-02-14 20:25:24 +01008626 newsrv = newsrv->next;
8627 }
8628
Willy Tarreaue42bd962014-09-16 16:21:19 +02008629 /* check if we have a frontend with "tcp-request content" looking at L7
8630 * with no inspect-delay
8631 */
8632 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008633 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8634 if (arule->action == ACT_TCP_CAPTURE &&
8635 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008636 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008637 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8638 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008639 break;
8640 }
8641
Christopher Faulete4e830d2017-09-18 14:51:41 +02008642 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008643 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8644 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8645 " This means that these rules will randomly find their contents. This can be fixed by"
8646 " setting the tcp-request inspect-delay.\n",
8647 proxy_type_str(curproxy), curproxy->id);
8648 err_code |= ERR_WARN;
8649 }
8650 }
8651
Christopher Fauletd7c91962015-04-30 11:48:27 +02008652 /* Check filter configuration, if any */
8653 cfgerr += flt_check(curproxy);
8654
Willy Tarreauc1a21672009-08-16 22:37:44 +02008655 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008656 if (!curproxy->accept)
8657 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008658
Willy Tarreauc1a21672009-08-16 22:37:44 +02008659 if (curproxy->tcp_req.inspect_delay ||
8660 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008661 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008662
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008663 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008664 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008665 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008666 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008667
8668 /* both TCP and HTTP must check switching rules */
8669 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008670
8671 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008672 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008673 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8674 curproxy->fe_rsp_ana |= AN_RES_FLT_START_FE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008675 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008676 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8677 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008678 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008679 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008680 }
8681
8682 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008683 if (curproxy->tcp_req.inspect_delay ||
8684 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8685 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8686
Emeric Brun97679e72010-09-23 17:56:44 +02008687 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8688 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8689
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008690 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008691 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008692 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008693 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008694
8695 /* If the backend does requires RDP cookie persistence, we have to
8696 * enable the corresponding analyser.
8697 */
8698 if (curproxy->options2 & PR_O2_RDPC_PRST)
8699 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008700
8701 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008702 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008703 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8704 curproxy->be_rsp_ana |= AN_RES_FLT_START_BE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008705 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008706 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8707 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008708 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008709 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008710 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008711 }
8712
8713 /***********************************************************/
8714 /* At this point, target names have already been resolved. */
8715 /***********************************************************/
8716
8717 /* Check multi-process mode compatibility */
8718
8719 if (global.nbproc > 1 && global.stats_fe) {
8720 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8721 unsigned long mask;
8722
8723 mask = nbits(global.nbproc);
8724 if (global.stats_fe->bind_proc)
8725 mask &= global.stats_fe->bind_proc;
8726
8727 if (bind_conf->bind_proc)
8728 mask &= bind_conf->bind_proc;
8729
8730 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008731 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008732 break;
8733 }
8734 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8735 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");
8736 }
8737 }
8738
8739 /* Make each frontend inherit bind-process from its listeners when not specified. */
8740 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8741 if (curproxy->bind_proc)
8742 continue;
8743
8744 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8745 unsigned long mask;
8746
Willy Tarreaue428b082015-05-04 21:57:58 +02008747 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008748 curproxy->bind_proc |= mask;
8749 }
8750
8751 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008752 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008753 }
8754
8755 if (global.stats_fe) {
8756 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8757 unsigned long mask;
8758
Cyril Bonté06181952016-02-24 00:14:54 +01008759 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008760 global.stats_fe->bind_proc |= mask;
8761 }
8762 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008763 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008764 }
8765
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008766 /* propagate bindings from frontends to backends. Don't do it if there
8767 * are any fatal errors as we must not call it with unresolved proxies.
8768 */
8769 if (!cfgerr) {
8770 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8771 if (curproxy->cap & PR_CAP_FE)
8772 propagate_processes(curproxy, NULL);
8773 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008774 }
8775
8776 /* Bind each unbound backend to all processes when not specified. */
8777 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8778 if (curproxy->bind_proc)
8779 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008780 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008781 }
8782
8783 /*******************************************************/
8784 /* At this step, all proxies have a non-null bind_proc */
8785 /*******************************************************/
8786
8787 /* perform the final checks before creating tasks */
8788
8789 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8790 struct listener *listener;
8791 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008792
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008793 /* Configure SSL for each bind line.
8794 * Note: if configuration fails at some point, the ->ctx member
8795 * remains NULL so that listeners can later detach.
8796 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008797 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008798 if (bind_conf->xprt->prepare_bind_conf &&
8799 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008800 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008801 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008802
Willy Tarreaue6b98942007-10-29 01:09:36 +01008803 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008804 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008805 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008806 int nbproc;
8807
8808 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008809 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008810 nbits(global.nbproc));
8811
8812 if (!nbproc) /* no intersection between listener and frontend */
8813 nbproc = 1;
8814
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008815 if (!listener->luid) {
8816 /* listener ID not set, use automatic numbering with first
8817 * spare entry starting with next_luid.
8818 */
8819 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8820 listener->conf.id.key = listener->luid = next_id;
8821 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008822 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008823 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008824
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008825 /* enable separate counters */
8826 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008827 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008828 if (!listener->name)
8829 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008830 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008831
Willy Tarreaue6b98942007-10-29 01:09:36 +01008832 if (curproxy->options & PR_O_TCP_NOLING)
8833 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008834 if (!listener->maxconn)
8835 listener->maxconn = curproxy->maxconn;
8836 if (!listener->backlog)
8837 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008838 if (!listener->maxaccept)
8839 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8840
8841 /* we want to have an optimal behaviour on single process mode to
8842 * maximize the work at once, but in multi-process we want to keep
8843 * some fairness between processes, so we target half of the max
8844 * number of events to be balanced over all the processes the proxy
8845 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8846 * used to disable the limit.
8847 */
8848 if (listener->maxaccept > 0) {
8849 if (nbproc > 1)
8850 listener->maxaccept = (listener->maxaccept + 1) / 2;
8851 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8852 }
8853
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008854 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008855 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008856 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008857
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008858 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008859 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008860
Willy Tarreau620408f2016-10-21 16:37:51 +02008861 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8862 listener->options |= LI_O_TCP_L5_RULES;
8863
Willy Tarreaude3041d2010-05-31 10:56:17 +02008864 if (curproxy->mon_mask.s_addr)
8865 listener->options |= LI_O_CHK_MONNET;
8866
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008867 /* smart accept mode is automatic in HTTP mode */
8868 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008869 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008870 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8871 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008872 }
8873
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008874 /* Release unused SSL configs */
8875 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008876 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8877 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008878 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008879
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008880 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008881 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008882 int count, maxproc = 0;
8883
8884 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008885 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008886 if (count > maxproc)
8887 maxproc = count;
8888 }
8889 /* backends have 0, frontends have 1 or more */
8890 if (maxproc != 1)
8891 Warning("Proxy '%s': in multi-process mode, stats will be"
8892 " limited to process assigned to the current request.\n",
8893 curproxy->id);
8894
Willy Tarreau102df612014-05-07 23:56:38 +02008895 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8896 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8897 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008898 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008899 }
Willy Tarreau102df612014-05-07 23:56:38 +02008900 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8901 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8902 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008903 }
8904 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008905
8906 /* create the task associated with the proxy */
8907 curproxy->task = task_new();
8908 if (curproxy->task) {
8909 curproxy->task->context = curproxy;
8910 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02008911 } else {
8912 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8913 curproxy->id);
8914 cfgerr++;
8915 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008916 }
8917
Willy Tarreaufbb78422011-06-05 15:38:35 +02008918 /* automatically compute fullconn if not set. We must not do it in the
8919 * loop above because cross-references are not yet fully resolved.
8920 */
8921 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8922 /* If <fullconn> is not set, let's set it to 10% of the sum of
8923 * the possible incoming frontend's maxconns.
8924 */
8925 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008926 /* we have the sum of the maxconns in <total>. We only
8927 * keep 10% of that sum to set the default fullconn, with
8928 * a hard minimum of 1 (to avoid a divide by zero).
8929 */
Emeric Brun3f783572017-01-12 11:21:28 +01008930 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008931 if (!curproxy->fullconn)
8932 curproxy->fullconn = 1;
8933 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008934 }
8935
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008936 /*
8937 * Recount currently required checks.
8938 */
8939
8940 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8941 int optnum;
8942
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008943 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8944 if (curproxy->options & cfg_opts[optnum].val)
8945 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008946
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008947 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8948 if (curproxy->options2 & cfg_opts2[optnum].val)
8949 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008950 }
8951
Willy Tarreau0fca4832015-05-01 19:12:05 +02008952 /* compute the required process bindings for the peers */
8953 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8954 if (curproxy->table.peers.p)
8955 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8956
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008957 if (cfg_peers) {
8958 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02008959 struct peer *p, *pb;
8960
Willy Tarreau1e273012015-05-01 19:15:17 +02008961 /* Remove all peers sections which don't have a valid listener,
8962 * which are not used by any table, or which are bound to more
8963 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008964 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008965 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02008966 while (*last) {
8967 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008968
8969 if (curpeers->state == PR_STSTOPPED) {
8970 /* the "disabled" keyword was present */
8971 if (curpeers->peers_fe)
8972 stop_proxy(curpeers->peers_fe);
8973 curpeers->peers_fe = NULL;
8974 }
8975 else if (!curpeers->peers_fe) {
8976 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8977 curpeers->id, localpeer);
8978 }
David Carliere6c39412015-07-02 07:00:17 +00008979 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008980 /* either it's totally stopped or too much used */
8981 if (curpeers->peers_fe->bind_proc) {
8982 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008983 "running in different processes (%d different ones). "
8984 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008985 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008986 cfgerr++;
8987 }
8988 stop_proxy(curpeers->peers_fe);
8989 curpeers->peers_fe = NULL;
8990 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008991 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008992 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008993 last = &curpeers->next;
8994 continue;
8995 }
8996
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008997 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008998 p = curpeers->remote;
8999 while (p) {
9000 pb = p->next;
9001 free(p->id);
9002 free(p);
9003 p = pb;
9004 }
9005
9006 /* Destroy and unlink this curpeers section.
9007 * Note: curpeers is backed up into *last.
9008 */
9009 free(curpeers->id);
9010 curpeers = curpeers->next;
9011 free(*last);
9012 *last = curpeers;
9013 }
9014 }
9015
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009016 /* initialize stick-tables on backend capable proxies. This must not
9017 * be done earlier because the data size may be discovered while parsing
9018 * other proxies.
9019 */
9020 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9021 if (curproxy->state == PR_STSTOPPED)
9022 continue;
9023
9024 if (!stktable_init(&curproxy->table)) {
9025 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9026 cfgerr++;
9027 }
9028 }
9029
Simon Horman0d16a402015-01-30 11:22:58 +09009030 if (mailers) {
9031 struct mailers *curmailers = mailers, **last;
9032 struct mailer *m, *mb;
9033
9034 /* Remove all mailers sections which don't have a valid listener.
9035 * This can happen when a mailers section is never referenced.
9036 */
9037 last = &mailers;
9038 while (*last) {
9039 curmailers = *last;
9040 if (curmailers->users) {
9041 last = &curmailers->next;
9042 continue;
9043 }
9044
9045 Warning("Removing incomplete section 'mailers %s'.\n",
9046 curmailers->id);
9047
9048 m = curmailers->mailer_list;
9049 while (m) {
9050 mb = m->next;
9051 free(m->id);
9052 free(m);
9053 m = mb;
9054 }
9055
9056 /* Destroy and unlink this curmailers section.
9057 * Note: curmailers is backed up into *last.
9058 */
9059 free(curmailers->id);
9060 curmailers = curmailers->next;
9061 free(*last);
9062 *last = curmailers;
9063 }
9064 }
9065
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009066 /* Update server_state_file_name to backend name if backend is supposed to use
9067 * a server-state file locally defined and none has been provided */
9068 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9069 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9070 curproxy->server_state_file_name == NULL)
9071 curproxy->server_state_file_name = strdup(curproxy->id);
9072 }
9073
Willy Tarreau34eb6712011-10-24 18:15:04 +02009074 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009075 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009076 MEM_F_SHARED);
9077
William Lallemand48b4bb42017-10-23 14:36:34 +02009078 list_for_each_entry(postparser, &postparsers, list) {
9079 if (postparser->func)
9080 cfgerr += postparser->func();
9081 }
9082
Willy Tarreaubb925012009-07-23 13:36:36 +02009083 if (cfgerr > 0)
9084 err_code |= ERR_ALERT | ERR_FATAL;
9085 out:
9086 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009087}
9088
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009089/*
9090 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9091 * parsing sessions.
9092 */
9093void cfg_register_keywords(struct cfg_kw_list *kwl)
9094{
9095 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9096}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009097
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009098/*
9099 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9100 */
9101void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9102{
9103 LIST_DEL(&kwl->list);
9104 LIST_INIT(&kwl->list);
9105}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009106
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009107/* this function register new section in the haproxy configuration file.
9108 * <section_name> is the name of this new section and <section_parser>
9109 * is the called parser. If two section declaration have the same name,
9110 * only the first declared is used.
9111 */
9112int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009113 int (*section_parser)(const char *, int, char **, int),
9114 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009115{
9116 struct cfg_section *cs;
9117
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009118 list_for_each_entry(cs, &sections, list) {
9119 if (strcmp(cs->section_name, section_name) == 0) {
9120 Alert("register section '%s': already registered.\n", section_name);
9121 return 0;
9122 }
9123 }
9124
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009125 cs = calloc(1, sizeof(*cs));
9126 if (!cs) {
9127 Alert("register section '%s': out of memory.\n", section_name);
9128 return 0;
9129 }
9130
9131 cs->section_name = section_name;
9132 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009133 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009134
9135 LIST_ADDQ(&sections, &cs->list);
9136
9137 return 1;
9138}
9139
William Lallemand48b4bb42017-10-23 14:36:34 +02009140/* this function register a new function which will be called once the haproxy
9141 * configuration file has been parsed. It's useful to check dependencies
9142 * between sections or to resolve items once everything is parsed.
9143 */
9144int cfg_register_postparser(char *name, int (*func)())
9145{
9146 struct cfg_postparser *cp;
9147
9148 cp = calloc(1, sizeof(*cp));
9149 if (!cp) {
9150 Alert("register postparser '%s': out of memory.\n", name);
9151 return 0;
9152 }
9153 cp->name = name;
9154 cp->func = func;
9155
9156 LIST_ADDQ(&postparsers, &cp->list);
9157
9158 return 1;
9159}
9160
Willy Tarreaubaaee002006-06-26 02:48:02 +02009161/*
David Carlier845efb52015-09-25 11:49:18 +01009162 * free all config section entries
9163 */
9164void cfg_unregister_sections(void)
9165{
9166 struct cfg_section *cs, *ics;
9167
9168 list_for_each_entry_safe(cs, ics, &sections, list) {
9169 LIST_DEL(&cs->list);
9170 free(cs);
9171 }
9172}
9173
Christopher Faulet7110b402016-10-26 11:09:44 +02009174void cfg_backup_sections(struct list *backup_sections)
9175{
9176 struct cfg_section *cs, *ics;
9177
9178 list_for_each_entry_safe(cs, ics, &sections, list) {
9179 LIST_DEL(&cs->list);
9180 LIST_ADDQ(backup_sections, &cs->list);
9181 }
9182}
9183
9184void cfg_restore_sections(struct list *backup_sections)
9185{
9186 struct cfg_section *cs, *ics;
9187
9188 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9189 LIST_DEL(&cs->list);
9190 LIST_ADDQ(&sections, &cs->list);
9191 }
9192}
9193
Willy Tarreau659fbf02016-05-26 17:55:28 +02009194__attribute__((constructor))
9195static void cfgparse_init(void)
9196{
9197 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009198 cfg_register_section("listen", cfg_parse_listen, NULL);
9199 cfg_register_section("frontend", cfg_parse_listen, NULL);
9200 cfg_register_section("backend", cfg_parse_listen, NULL);
9201 cfg_register_section("defaults", cfg_parse_listen, NULL);
9202 cfg_register_section("global", cfg_parse_global, NULL);
9203 cfg_register_section("userlist", cfg_parse_users, NULL);
9204 cfg_register_section("peers", cfg_parse_peers, NULL);
9205 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9206 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9207 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009208}
9209
David Carlier845efb52015-09-25 11:49:18 +01009210/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009211 * Local variables:
9212 * c-indent-level: 8
9213 * c-basic-offset: 8
9214 * End:
9215 */