blob: 794148c94460a7e8c902315f1e46d9d8287f0845 [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>
Emeric Brunc60def82017-09-27 14:59:38 +020045#include <common/hathreads.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046
47#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020048#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020049#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010051#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020052#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090053#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020054#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010055#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056
Willy Tarreaueb0c6142007-05-07 00:53:22 +020057#include <proto/acl.h>
Christopher Faulet4fce0d82017-09-18 11:57:31 +020058#include <proto/action.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010059#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020061#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020063#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020064#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010065#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020066#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020067#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020068#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020069#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010070#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020071#include <proto/lb_fwlc.h>
72#include <proto/lb_fwrr.h>
73#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020075#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020076#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
William Lallemandd2ff56d2017-10-16 11:06:50 +0200131 int (*post_section_parser)();
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
William Lallemand48b4bb42017-10-23 14:36:34 +0200139/* store post configuration parsing */
140
141struct cfg_postparser {
142 struct list list;
143 char *name;
144 int (*func)();
145};
146
147struct list postparsers = LIST_HEAD_INIT(postparsers);
148
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100151 const char *name;
152 unsigned int val;
153 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100154 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100156};
157
158/* proxy->options */
159static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100160{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
162 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
163 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
165 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
166 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200168 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200169 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100170 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
172 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
173 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100175#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100179#endif
180
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100182};
183
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184/* proxy->options2 */
185static const struct cfg_opt cfg_opts2[] =
186{
187#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
189 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
190 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100191#else
192 { "splice-request", 0, 0, 0, 0 },
193 { "splice-response", 0, 0, 0, 0 },
194 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
197 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
198 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
199 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
200 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
201 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
202 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
203 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
204 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400205 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100206 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200207 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200208 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100209 { NULL, 0, 0, 0 }
210};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Willy Tarreau6daf3432008-01-22 16:44:08 +0100212static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
214int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100215int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100216char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200218/* List head of all known configuration keywords */
219static struct cfg_kw_list cfg_keywords = {
220 .list = LIST_HEAD_INIT(cfg_keywords.list)
221};
222
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223/*
224 * converts <str> to a list of listeners which are dynamically allocated.
225 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
226 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
227 * - <port> is a numerical port from 1 to 65535 ;
228 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
229 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200230 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
231 * not NULL, it must be a valid pointer to either NULL or a freeable area that
232 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200234int 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 +0200235{
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 int port, end;
238
239 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200240
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 while (next && *next) {
William Lallemand75ea0a02017-11-15 19:02:58 +0100242 int inherited = 0;
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200243 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
246 str = next;
247 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100248 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249 *next++ = 0;
250 }
251
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100252 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200253 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200254 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100255 if (!ss2)
256 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100258 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100259 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200260 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100264 if (!port || !end) {
265 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
266 goto fail;
267 }
268
Emeric Bruned760922010-10-22 17:59:25 +0200269 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200270 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200271 goto fail;
272 }
273
274 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200275 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200276 goto fail;
277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100279 else if (ss2->ss_family == AF_UNSPEC) {
280 socklen_t addr_len;
William Lallemand75ea0a02017-11-15 19:02:58 +0100281 inherited = 1;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282
283 /* We want to attach to an already bound fd whose number
284 * is in the addr part of ss2 when cast to sockaddr_in.
285 * Note that by definition there is a single listener.
286 * We still have to determine the address family to
287 * register the correct protocol.
288 */
289 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
290 addr_len = sizeof(*ss2);
291 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
292 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
293 goto fail;
294 }
295
296 port = end = get_host_port(ss2);
297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100299 /* OK the address looks correct */
William Lallemand75ea0a02017-11-15 19:02:58 +0100300 if (!create_listeners(bind_conf, ss2, port, end, fd, inherited, err)) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200301 memprintf(err, "%s for address '%s'.\n", *err, str);
302 goto fail;
303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 } /* end while(next) */
305 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200306 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307 fail:
308 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310}
311
William Lallemand6e62fb62015-04-28 16:55:23 +0200312/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100313 * Report an error in <msg> when there are too many arguments. This version is
314 * intended to be used by keyword parsers so that the message will be included
315 * into the general error message. The index is the current keyword in args.
316 * Return 0 if the number of argument is correct, otherwise build a message and
317 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
318 * message may also be null, it will simply not be produced (useful to check only).
319 * <msg> and <err_code> are only affected on error.
320 */
321int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
322{
323 int i;
324
325 if (!*args[index + maxarg + 1])
326 return 0;
327
328 if (msg) {
329 *msg = NULL;
330 memprintf(msg, "%s", args[0]);
331 for (i = 1; i <= index; i++)
332 memprintf(msg, "%s %s", *msg, args[i]);
333
334 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
335 }
336 if (err_code)
337 *err_code |= ERR_ALERT | ERR_FATAL;
338
339 return 1;
340}
341
342/*
343 * same as too_many_args_idx with a 0 index
344 */
345int too_many_args(int maxarg, char **args, char **msg, int *err_code)
346{
347 return too_many_args_idx(maxarg, 0, args, msg, err_code);
348}
349
350/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200351 * Report a fatal Alert when there is too much arguments
352 * The index is the current keyword in args
353 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
354 * Fill err_code with an ERR_ALERT and an ERR_FATAL
355 */
356int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
357{
358 char *kw = NULL;
359 int i;
360
361 if (!*args[index + maxarg + 1])
362 return 0;
363
364 memprintf(&kw, "%s", args[0]);
365 for (i = 1; i <= index; i++) {
366 memprintf(&kw, "%s %s", kw, args[i]);
367 }
368
369 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
370 free(kw);
371 *err_code |= ERR_ALERT | ERR_FATAL;
372 return 1;
373}
374
375/*
376 * same as alertif_too_many_args_idx with a 0 index
377 */
378int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
379{
380 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
381}
382
Willy Tarreau620408f2016-10-21 16:37:51 +0200383/* Report a warning if a rule is placed after a 'tcp-request session' rule.
384 * Return 1 if the warning has been emitted, otherwise 0.
385 */
386int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
387{
388 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
389 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
390 file, line, arg);
391 return 1;
392 }
393 return 0;
394}
395
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200396/* Report a warning if a rule is placed after a 'tcp-request content' rule.
397 * Return 1 if the warning has been emitted, otherwise 0.
398 */
399int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
400{
401 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
402 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
403 file, line, arg);
404 return 1;
405 }
406 return 0;
407}
408
Willy Tarreau61d18892009-03-31 10:49:21 +0200409/* Report a warning if a rule is placed after a 'block' rule.
410 * Return 1 if the warning has been emitted, otherwise 0.
411 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200414 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
416 file, line, arg);
417 return 1;
418 }
419 return 0;
420}
421
Willy Tarreau5002f572014-04-23 01:32:02 +0200422/* Report a warning if a rule is placed after an 'http_request' rule.
423 * Return 1 if the warning has been emitted, otherwise 0.
424 */
425int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
426{
427 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
428 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
429 file, line, arg);
430 return 1;
431 }
432 return 0;
433}
434
Willy Tarreau61d18892009-03-31 10:49:21 +0200435/* Report a warning if a rule is placed after a reqrewrite rule.
436 * Return 1 if the warning has been emitted, otherwise 0.
437 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100438int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200439{
440 if (proxy->req_exp) {
441 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
442 file, line, arg);
443 return 1;
444 }
445 return 0;
446}
447
448/* Report a warning if a rule is placed after a reqadd rule.
449 * Return 1 if the warning has been emitted, otherwise 0.
450 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100453 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200454 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
455 file, line, arg);
456 return 1;
457 }
458 return 0;
459}
460
461/* Report a warning if a rule is placed after a redirect rule.
462 * Return 1 if the warning has been emitted, otherwise 0.
463 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100464int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200465{
466 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
467 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
468 file, line, arg);
469 return 1;
470 }
471 return 0;
472}
473
474/* Report a warning if a rule is placed after a 'use_backend' rule.
475 * Return 1 if the warning has been emitted, otherwise 0.
476 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100477int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200478{
479 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
480 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
481 file, line, arg);
482 return 1;
483 }
484 return 0;
485}
486
Willy Tarreauee445d92014-04-23 01:39:04 +0200487/* Report a warning if a rule is placed after a 'use-server' rule.
488 * Return 1 if the warning has been emitted, otherwise 0.
489 */
490int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
491{
492 if (!LIST_ISEMPTY(&proxy->server_rules)) {
493 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
494 file, line, arg);
495 return 1;
496 }
497 return 0;
498}
499
Willy Tarreaud39ad442016-11-25 15:16:12 +0100500/* report a warning if a redirect rule is dangerously placed */
501int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200502{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100503 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200504 warnif_rule_after_use_server(proxy, file, line, arg);
505}
506
Willy Tarreaud39ad442016-11-25 15:16:12 +0100507/* report a warning if a reqadd rule is dangerously placed */
508int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200509{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100510 return warnif_rule_after_redirect(proxy, file, line, arg) ||
511 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200512}
513
Willy Tarreaud39ad442016-11-25 15:16:12 +0100514/* report a warning if a reqxxx rule is dangerously placed */
515int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200516{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100517 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
518 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200519}
520
521/* report a warning if an http-request rule is dangerously placed */
522int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
523{
Willy Tarreau61d18892009-03-31 10:49:21 +0200524 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200526}
527
Willy Tarreaud39ad442016-11-25 15:16:12 +0100528/* report a warning if a block rule is dangerously placed */
529int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200530{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100531 return warnif_rule_after_http_req(proxy, file, line, arg) ||
532 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaud39ad442016-11-25 15:16:12 +0100535/* report a warning if a "tcp request content" rule is dangerously placed */
536int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200537{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100538 return warnif_rule_after_block(proxy, file, line, arg) ||
539 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200540}
541
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542/* report a warning if a "tcp request session" rule is dangerously placed */
543int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200544{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100545 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
546 warnif_misplaced_tcp_cont(proxy, file, line, arg);
547}
548
549/* report a warning if a "tcp request connection" rule is dangerously placed */
550int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
551{
552 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
553 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200554}
555
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556/* Report it if a request ACL condition uses some keywords that are incompatible
557 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
558 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
559 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100560 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100562{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100563 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567 return 0;
568
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100569 acl = acl_cond_conflicts(cond, where);
570 if (acl) {
571 if (acl->name && *acl->name)
572 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
573 file, line, acl->name, sample_ckp_names(where));
574 else
575 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 +0200576 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100577 return ERR_WARN;
578 }
579 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100580 return 0;
581
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 if (acl->name && *acl->name)
583 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200584 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100585 else
586 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200587 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100588 return ERR_WARN;
589}
590
Christopher Faulet62519022017-10-16 15:49:32 +0200591/* Parse a string representing a process number or a set of processes. It must
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100592 * be "all", "odd", "even", a number between 1 and <LONGBITS> or a range with
593 * two such numbers delimited by a dash ('-'). It returns a mask where bits are
594 * set for corresponding processes or 0 if an error occured.
Christopher Faulet62519022017-10-16 15:49:32 +0200595 *
596 * Note: this function can also be used to parse a thread number or a set of
597 * threads.
598 */
599static unsigned long parse_process_number(const char *arg)
600{
601 unsigned long proc = 0;
602
603 if (strcmp(arg, "all") == 0)
604 proc = ~0UL;
605 else if (strcmp(arg, "odd") == 0)
606 proc = ~0UL/3UL; /* 0x555....555 */
607 else if (strcmp(arg, "even") == 0)
608 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
609 else {
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100610 char *dash;
611 unsigned int low, high;
612
613 if (!isdigit((int)*arg))
614 goto end;
615
616 low = high = str2uic(arg);
617 if ((dash = strchr(arg, '-')) != NULL)
618 high = str2uic(dash + 1);
619 if (high < low) {
620 unsigned int swap = low;
621 low = high;
622 high = swap;
623 }
624
625 if (low < 1 || low >= LONGBITS || high >= LONGBITS)
626 goto end;
627
628 for (;low <= high; low++)
629 proc |= 1UL << (low-1);
Christopher Faulet62519022017-10-16 15:49:32 +0200630 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100631
632 end:
Christopher Faulet62519022017-10-16 15:49:32 +0200633 return proc;
634}
635
636/* Parse cpu sets. Each CPU set is either a unique number between 0 and
637 * <LONGBITS> or a range with two such numbers delimited by a dash
638 * ('-'). Multiple CPU numbers or ranges may be specified. On success, it
639 * returns 0. otherwise it returns 1 with an error message in <err>.
640 */
641static unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
642{
643 int cur_arg = 0;
644
645 *cpu_set = 0;
646 while (*args[cur_arg]) {
647 char *dash;
648 unsigned int low, high;
649
650 if (!isdigit((int)*args[cur_arg])) {
651 memprintf(err, "'%s' is not a CPU range.\n", args[cur_arg]);
652 return -1;
653 }
654
655 low = high = str2uic(args[cur_arg]);
656 if ((dash = strchr(args[cur_arg], '-')) != NULL)
657 high = str2uic(dash + 1);
658
659 if (high < low) {
660 unsigned int swap = low;
661 low = high;
662 high = swap;
663 }
664
665 if (high >= LONGBITS) {
666 memprintf(err, "supports CPU numbers from 0 to %d.\n", LONGBITS - 1);
667 return 1;
668 }
669
670 while (low <= high)
671 *cpu_set |= 1UL << low++;
672
673 cur_arg++;
674 }
675 return 0;
676}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 * parse a line in a <global> section. Returns the error code, 0 if OK, or
679 * any combination of :
680 * - ERR_ABORT: must abort ASAP
681 * - ERR_FATAL: we can continue parsing but not start the service
682 * - ERR_WARN: a warning has been emitted
683 * - ERR_ALERT: an alert has been emitted
684 * Only the two first ones can stop processing, the two others are just
685 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200686 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200687int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688{
Willy Tarreau058e9072009-07-20 09:30:05 +0200689 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200690 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691
692 if (!strcmp(args[0], "global")) { /* new section */
693 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200694 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(0, file, linenum, args, &err_code))
699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 global.mode |= MODE_DAEMON;
701 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200702 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200704 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200705 if (*args[1]) {
706 if (!strcmp(args[1], "exit-on-failure")) {
707 global.tune.options |= GTUNE_EXIT_ONFAILURE;
708 } else {
709 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200714 global.mode |= MODE_MWORKER;
715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(0, file, linenum, args, &err_code))
718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 global.mode |= MODE_DEBUG;
720 }
721 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200722 if (alertif_too_many_args(0, file, linenum, args, &err_code))
723 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100724 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200725 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200726 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200727 if (alertif_too_many_args(0, file, linenum, args, &err_code))
728 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100729 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200732 if (alertif_too_many_args(0, file, linenum, args, &err_code))
733 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100734 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200735 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100736 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200737 if (alertif_too_many_args(0, file, linenum, args, &err_code))
738 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100739 global.tune.options &= ~GTUNE_USE_SPLICE;
740 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200741 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200742 if (alertif_too_many_args(0, file, linenum, args, &err_code))
743 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200744 global.tune.options &= ~GTUNE_USE_GAI;
745 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000746 else if (!strcmp(args[0], "noreuseport")) {
747 if (alertif_too_many_args(0, file, linenum, args, &err_code))
748 goto out;
749 global.tune.options &= ~GTUNE_USE_REUSEPORT;
750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200752 if (alertif_too_many_args(0, file, linenum, args, &err_code))
753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 global.mode |= MODE_QUIET;
755 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200756 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200757 if (alertif_too_many_args(1, file, linenum, args, &err_code))
758 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200759 if (global.tune.maxpollevents != 0) {
760 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT;
762 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200763 }
764 if (*(args[1]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200768 }
769 global.tune.maxpollevents = atol(args[1]);
770 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100771 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
773 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100774 if (global.tune.maxaccept != 0) {
775 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200776 err_code |= ERR_ALERT;
777 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100778 }
779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100783 }
784 global.tune.maxaccept = atol(args[1]);
785 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200786 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200787 if (alertif_too_many_args(1, file, linenum, args, &err_code))
788 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200789 if (*(args[1]) == 0) {
790 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
793 }
794 global.tune.chksize = atol(args[1]);
795 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100796 else if (!strcmp(args[0], "tune.recv_enough")) {
797 if (alertif_too_many_args(1, file, linenum, args, &err_code))
798 goto out;
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.recv_enough = atol(args[1]);
805 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100806 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200807 if (alertif_too_many_args(1, file, linenum, args, &err_code))
808 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100809 if (*(args[1]) == 0) {
810 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
811 err_code |= ERR_ALERT | ERR_FATAL;
812 goto out;
813 }
814 global.tune.buf_limit = atol(args[1]);
815 if (global.tune.buf_limit) {
816 if (global.tune.buf_limit < 3)
817 global.tune.buf_limit = 3;
818 if (global.tune.buf_limit <= global.tune.reserved_bufs)
819 global.tune.buf_limit = global.tune.reserved_bufs + 1;
820 }
821 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100822 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200823 if (alertif_too_many_args(1, file, linenum, args, &err_code))
824 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.reserved_bufs = atol(args[1]);
831 if (global.tune.reserved_bufs < 2)
832 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100833 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
834 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100835 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200836 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
843 }
844 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200845 if (global.tune.bufsize <= 0) {
846 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
849 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200850 }
851 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200860 if (global.tune.maxrewrite < 0) {
861 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100866 else if (!strcmp(args[0], "tune.idletimer")) {
867 unsigned int idle;
868 const char *res;
869
William Lallemand1a748ae2015-05-19 16:37:23 +0200870 if (alertif_too_many_args(1, file, linenum, args, &err_code))
871 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100872 if (*(args[1]) == 0) {
873 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877
878 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
879 if (res) {
880 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
881 file, linenum, *res, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885
886 if (idle > 65535) {
887 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.tune.idle_timer = idle;
892 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100893 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200894 if (alertif_too_many_args(1, file, linenum, args, &err_code))
895 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100896 if (global.tune.client_rcvbuf != 0) {
897 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT;
899 goto out;
900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
905 }
906 global.tune.client_rcvbuf = atol(args[1]);
907 }
908 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200909 if (alertif_too_many_args(1, file, linenum, args, &err_code))
910 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100911 if (global.tune.server_rcvbuf != 0) {
912 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT;
914 goto out;
915 }
916 if (*(args[1]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 global.tune.server_rcvbuf = atol(args[1]);
922 }
923 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200924 if (alertif_too_many_args(1, file, linenum, args, &err_code))
925 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100926 if (global.tune.client_sndbuf != 0) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT;
929 goto out;
930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.tune.client_sndbuf = atol(args[1]);
937 }
938 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200939 if (alertif_too_many_args(1, file, linenum, args, &err_code))
940 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100941 if (global.tune.server_sndbuf != 0) {
942 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
943 err_code |= ERR_ALERT;
944 goto out;
945 }
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 global.tune.server_sndbuf = atol(args[1]);
952 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200953 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200954 if (alertif_too_many_args(1, file, linenum, args, &err_code))
955 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200956 if (*(args[1]) == 0) {
957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961 global.tune.pipesize = atol(args[1]);
962 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100963 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200964 if (alertif_too_many_args(1, file, linenum, args, &err_code))
965 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
971 global.tune.cookie_len = atol(args[1]) + 1;
972 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200973 else if (!strcmp(args[0], "tune.http.logurilen")) {
974 if (alertif_too_many_args(1, file, linenum, args, &err_code))
975 goto out;
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981 global.tune.requri_len = atol(args[1]) + 1;
982 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200983 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200984 if (alertif_too_many_args(1, file, linenum, args, &err_code))
985 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200986 if (*(args[1]) == 0) {
987 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
990 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200991 global.tune.max_http_hdr = atoi(args[1]);
992 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
993 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
994 file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200998 }
William Lallemandf3747832012-11-09 12:33:10 +0100999 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001000 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1001 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001002 if (*args[1]) {
1003 global.tune.comp_maxlevel = atoi(args[1]);
1004 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1005 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1006 file, linenum, args[0]);
1007 err_code |= ERR_ALERT | ERR_FATAL;
1008 goto out;
1009 }
1010 } else {
1011 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1012 file, linenum, args[0]);
1013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
1015 }
1016 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001017 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1018 if (*args[1]) {
1019 global.tune.pattern_cache = atoi(args[1]);
1020 if (global.tune.pattern_cache < 0) {
1021 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 } else {
1027 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1028 file, linenum, args[0]);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031 }
1032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001034 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001037 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001038 err_code |= ERR_ALERT;
1039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 }
1041 if (*(args[1]) == 0) {
1042 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001046 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1047 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]);
1048 err_code |= ERR_WARN;
1049 goto out;
1050 }
1051
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
1053 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001054 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001057 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 err_code |= ERR_ALERT;
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 if (*(args[1]) == 0) {
1062 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001066 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1067 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]);
1068 err_code |= ERR_WARN;
1069 goto out;
1070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 }
Simon Horman98637e52014-06-20 12:30:16 +09001072 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001073 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1074 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001075 global.external_check = 1;
1076 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001077 /* user/group name handling */
1078 else if (!strcmp(args[0], "user")) {
1079 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001080 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1081 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001082 if (global.uid != 0) {
1083 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001084 err_code |= ERR_ALERT;
1085 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001086 }
1087 errno = 0;
1088 ha_user = getpwnam(args[1]);
1089 if (ha_user != NULL) {
1090 global.uid = (int)ha_user->pw_uid;
1091 }
1092 else {
1093 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 +02001094 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001095 }
1096 }
1097 else if (!strcmp(args[0], "group")) {
1098 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001099 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1100 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001101 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001102 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001103 err_code |= ERR_ALERT;
1104 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001105 }
1106 errno = 0;
1107 ha_group = getgrnam(args[1]);
1108 if (ha_group != NULL) {
1109 global.gid = (int)ha_group->gr_gid;
1110 }
1111 else {
1112 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 +02001113 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001114 }
1115 }
1116 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001118 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 if (*(args[1]) == 0) {
1121 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 }
1125 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001126 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1127 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1128 file, linenum, args[0], LONGBITS, global.nbproc);
1129 err_code |= ERR_ALERT | ERR_FATAL;
1130 goto out;
1131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
Christopher Fauletbe0faa22017-08-29 15:37:10 +02001133 else if (!strcmp(args[0], "nbthread")) {
1134 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1135 goto out;
1136 if (*(args[1]) == 0) {
1137 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto out;
1140 }
1141 global.nbthread = atol(args[1]);
1142 if (global.nbthread < 1 || global.nbthread > LONGBITS) {
1143 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1144 file, linenum, args[0], LONGBITS, global.nbthread);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
1148#ifndef USE_THREAD
1149 if (global.nbthread > 1) {
1150 Alert("HAProxy is not compiled with threads support, please check build options for USE_THREAD.\n");
1151 global.nbthread = 1;
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
1154 }
1155#endif
1156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001158 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 if (global.maxconn != 0) {
1161 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001162 err_code |= ERR_ALERT;
1163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 }
1165 if (*(args[1]) == 0) {
1166 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001167 err_code |= ERR_ALERT | ERR_FATAL;
1168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 }
1170 global.maxconn = atol(args[1]);
1171#ifdef SYSTEM_MAXCONN
1172 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1173 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);
1174 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001175 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001176 }
1177#endif /* SYSTEM_MAXCONN */
1178 }
Emeric Brun850efd52014-01-29 12:24:34 +01001179 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001182 if (*(args[1]) == 0) {
1183 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187 if (strcmp(args[1],"none") == 0)
1188 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1189 else if (strcmp(args[1],"required") == 0)
1190 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1191 else {
1192 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
1196 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001197 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001198 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1199 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001200 if (global.cps_lim != 0) {
1201 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1202 err_code |= ERR_ALERT;
1203 goto out;
1204 }
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
1209 }
1210 global.cps_lim = atol(args[1]);
1211 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001212 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001215 if (global.sps_lim != 0) {
1216 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1217 err_code |= ERR_ALERT;
1218 goto out;
1219 }
1220 if (*(args[1]) == 0) {
1221 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225 global.sps_lim = atol(args[1]);
1226 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001227 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001228 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1229 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001230 if (global.ssl_lim != 0) {
1231 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1232 err_code |= ERR_ALERT;
1233 goto out;
1234 }
1235 if (*(args[1]) == 0) {
1236 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240 global.ssl_lim = atol(args[1]);
1241 }
William Lallemandd85f9172012-11-09 17:05:39 +01001242 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001243 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1244 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001245 if (*(args[1]) == 0) {
1246 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250 global.comp_rate_lim = atoi(args[1]) * 1024;
1251 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001252 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001253 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1254 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001255 if (global.maxpipes != 0) {
1256 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001257 err_code |= ERR_ALERT;
1258 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001259 }
1260 if (*(args[1]) == 0) {
1261 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001264 }
1265 global.maxpipes = atol(args[1]);
1266 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001267 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001268 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1269 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001270 if (*(args[1]) == 0) {
1271 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
William Lallemande3a7d992012-11-20 11:25:20 +01001275 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001276 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001277 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001280 if (*(args[1]) == 0) {
1281 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001286 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001287 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
1290 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001291 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001292
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001294 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296 if (global.rlimit_nofile != 0) {
1297 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001298 err_code |= ERR_ALERT;
1299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 }
1301 if (*(args[1]) == 0) {
1302 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 }
1306 global.rlimit_nofile = atol(args[1]);
1307 }
1308 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001309 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 if (global.chroot != NULL) {
1312 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001313 err_code |= ERR_ALERT;
1314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 }
1316 if (*(args[1]) == 0) {
1317 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 }
1321 global.chroot = strdup(args[1]);
1322 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001323 else if (!strcmp(args[0], "description")) {
1324 int i, len=0;
1325 char *d;
1326
1327 if (!*args[1]) {
1328 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
Willy Tarreau348acfe2014-04-14 15:00:39 +02001334 for (i = 1; *args[i]; i++)
1335 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001336
1337 if (global.desc)
1338 free(global.desc);
1339
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001340 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001341
Willy Tarreau348acfe2014-04-14 15:00:39 +02001342 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1343 for (i = 2; *args[i]; i++)
1344 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001345 }
1346 else if (!strcmp(args[0], "node")) {
1347 int i;
1348 char c;
1349
William Lallemand1a748ae2015-05-19 16:37:23 +02001350 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1351 goto out;
1352
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001353 for (i=0; args[1][i]; i++) {
1354 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001355 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1356 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001357 break;
1358 }
1359
1360 if (!i || args[1][i]) {
1361 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1362 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1363 file, linenum, args[0]);
1364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
1366 }
1367
1368 if (global.node)
1369 free(global.node);
1370
1371 global.node = strdup(args[1]);
1372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001374 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if (global.pidfile != NULL) {
1377 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001378 err_code |= ERR_ALERT;
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
1381 if (*(args[1]) == 0) {
1382 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 }
1386 global.pidfile = strdup(args[1]);
1387 }
Emeric Bruned760922010-10-22 17:59:25 +02001388 else if (!strcmp(args[0], "unix-bind")) {
1389 int cur_arg = 1;
1390 while (*(args[cur_arg])) {
1391 if (!strcmp(args[cur_arg], "prefix")) {
1392 if (global.unix_bind.prefix != NULL) {
1393 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1394 err_code |= ERR_ALERT;
1395 cur_arg += 2;
1396 continue;
1397 }
1398
1399 if (*(args[cur_arg+1]) == 0) {
1400 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1401 err_code |= ERR_ALERT | ERR_FATAL;
1402 goto out;
1403 }
1404 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1405 cur_arg += 2;
1406 continue;
1407 }
1408
1409 if (!strcmp(args[cur_arg], "mode")) {
1410
1411 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1412 cur_arg += 2;
1413 continue;
1414 }
1415
1416 if (!strcmp(args[cur_arg], "uid")) {
1417
1418 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1419 cur_arg += 2;
1420 continue;
1421 }
1422
1423 if (!strcmp(args[cur_arg], "gid")) {
1424
1425 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1426 cur_arg += 2;
1427 continue;
1428 }
1429
1430 if (!strcmp(args[cur_arg], "user")) {
1431 struct passwd *user;
1432
1433 user = getpwnam(args[cur_arg + 1]);
1434 if (!user) {
1435 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1436 file, linenum, args[0], args[cur_arg + 1 ]);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 goto out;
1439 }
1440
1441 global.unix_bind.ux.uid = user->pw_uid;
1442 cur_arg += 2;
1443 continue;
1444 }
1445
1446 if (!strcmp(args[cur_arg], "group")) {
1447 struct group *group;
1448
1449 group = getgrnam(args[cur_arg + 1]);
1450 if (!group) {
1451 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1452 file, linenum, args[0], args[cur_arg + 1 ]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto out;
1455 }
1456
1457 global.unix_bind.ux.gid = group->gr_gid;
1458 cur_arg += 2;
1459 continue;
1460 }
1461
Willy Tarreaub48f9582011-09-05 01:17:06 +02001462 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001463 file, linenum, args[0]);
1464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
1466 }
1467 }
William Lallemand0f99e342011-10-12 17:50:54 +02001468 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1469 /* delete previous herited or defined syslog servers */
1470 struct logsrv *back;
1471 struct logsrv *tmp;
1472
1473 if (*(args[1]) != 0) {
1474 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
1477 }
1478
1479 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1480 LIST_DEL(&tmp->list);
1481 free(tmp);
1482 }
1483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001485 struct sockaddr_storage *sk;
1486 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001487 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001488 int arg = 0;
1489 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001490
William Lallemand1a748ae2015-05-19 16:37:23 +02001491 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1492 goto out;
1493
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 if (*(args[1]) == 0 || *(args[2]) == 0) {
1495 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 }
William Lallemand0f99e342011-10-12 17:50:54 +02001499
Vincent Bernat02779b62016-04-03 13:48:43 +02001500 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001501
Willy Tarreau18324f52014-06-27 18:10:07 +02001502 /* just after the address, a length may be specified */
1503 if (strcmp(args[arg+2], "len") == 0) {
1504 len = atoi(args[arg+3]);
1505 if (len < 80 || len > 65535) {
1506 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1507 file, linenum, args[arg+3]);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto out;
1510 }
1511 logsrv->maxlen = len;
1512
1513 /* skip these two args */
1514 arg += 2;
1515 }
1516 else
1517 logsrv->maxlen = MAX_SYSLOG_LEN;
1518
Christopher Faulet084aa962017-08-29 16:54:41 +02001519 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001520 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001521
Dragan Dosen1322d092015-09-22 16:05:32 +02001522 /* after the length, a format may be specified */
1523 if (strcmp(args[arg+2], "format") == 0) {
1524 logsrv->format = get_log_format(args[arg+3]);
1525 if (logsrv->format < 0) {
1526 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1527 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001528 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001529 goto out;
1530 }
1531
1532 /* skip these two args */
1533 arg += 2;
1534 }
1535
David Carlier97880bb2016-04-08 10:35:26 +01001536 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1537 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001538 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001539 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001540
Willy Tarreau18324f52014-06-27 18:10:07 +02001541 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001542 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001543 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001545 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001546 }
1547
William Lallemand0f99e342011-10-12 17:50:54 +02001548 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001549 if (*(args[arg+3])) {
1550 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001551 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001552 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001553 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001554 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 }
1556 }
1557
William Lallemand0f99e342011-10-12 17:50:54 +02001558 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001559 if (*(args[arg+4])) {
1560 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001561 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001562 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001563 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001564 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001565 }
1566 }
1567
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001568 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001569 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001570 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001571 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001572 free(logsrv);
1573 goto out;
1574 }
1575 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001576
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001577 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001578 if (port1 != port2) {
1579 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1580 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001581 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001582 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001583 goto out;
1584 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001585
William Lallemand0f99e342011-10-12 17:50:54 +02001586 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001587 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001588 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590
William Lallemand0f99e342011-10-12 17:50:54 +02001591 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001592 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001593 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1594 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001595
1596 if (global.log_send_hostname != NULL) {
1597 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1598 err_code |= ERR_ALERT;
1599 goto out;
1600 }
1601
1602 if (*(args[1]))
1603 name = args[1];
1604 else
1605 name = hostname;
1606
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001607 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001608 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001609 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001610 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1611 if (global.server_state_base != NULL) {
1612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1613 err_code |= ERR_ALERT;
1614 goto out;
1615 }
1616
1617 if (!*(args[1])) {
1618 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1619 err_code |= ERR_FATAL;
1620 goto out;
1621 }
1622
1623 global.server_state_base = strdup(args[1]);
1624 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001625 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1626 if (global.server_state_file != NULL) {
1627 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1628 err_code |= ERR_ALERT;
1629 goto out;
1630 }
1631
1632 if (!*(args[1])) {
1633 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1634 err_code |= ERR_FATAL;
1635 goto out;
1636 }
1637
1638 global.server_state_file = strdup(args[1]);
1639 }
Kevinm48936af2010-12-22 16:08:21 +00001640 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001641 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1642 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001643 if (*(args[1]) == 0) {
1644 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
1647 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001648 chunk_destroy(&global.log_tag);
1649 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001650 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001651 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001652 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1653 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001654 if (global.spread_checks != 0) {
1655 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001656 err_code |= ERR_ALERT;
1657 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001658 }
1659 if (*(args[1]) == 0) {
1660 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
1662 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001663 }
1664 global.spread_checks = atol(args[1]);
1665 if (global.spread_checks < 0 || global.spread_checks > 50) {
1666 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001667 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001670 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1671 const char *err;
1672 unsigned int val;
1673
William Lallemand1a748ae2015-05-19 16:37:23 +02001674 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1675 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001676 if (*(args[1]) == 0) {
1677 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
1680 }
1681
1682 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1683 if (err) {
1684 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1685 err_code |= ERR_ALERT | ERR_FATAL;
1686 }
1687 global.max_spread_checks = val;
1688 if (global.max_spread_checks < 0) {
1689 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1690 err_code |= ERR_ALERT | ERR_FATAL;
1691 }
1692 }
Christopher Faulet62519022017-10-16 15:49:32 +02001693 else if (strcmp(args[0], "cpu-map") == 0) {
1694 /* map a process list to a CPU set */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001695#ifdef USE_CPU_AFFINITY
Christopher Faulet62519022017-10-16 15:49:32 +02001696 unsigned long proc, cpus;
1697 int i;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001698
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001699 if (!*args[1] || !*args[2]) {
1700 Alert("parsing [%s:%d] : %s expects a process number "
1701 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
Christopher Faulet62519022017-10-16 15:49:32 +02001702 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001703 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001707
1708 proc = parse_process_number(args[1]);
1709 if (!proc) {
1710 Alert("parsing [%s:%d] : %s : '%s' is not a valid PROC number "
1711 " ('all', 'odd', 'even', a number from 1 to %d or a range).\n",
1712 file, linenum, args[0], args[1], LONGBITS);
1713 err_code |= ERR_ALERT | ERR_FATAL;
1714 goto out;
1715 }
1716
Christopher Faulet62519022017-10-16 15:49:32 +02001717 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
1718 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001721 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001722 for (i = 0; i < LONGBITS; i++)
1723 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001724 global.cpu_map[i] = cpus;
1725#else
Christopher Faulet62519022017-10-16 15:49:32 +02001726 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1727 file, linenum, args[0]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
Christopher Faulet62519022017-10-16 15:49:32 +02001730#endif /* ! USE_CPU_AFFINITY */
1731 }
1732 else if (strcmp(args[0], "thread-map") == 0) {
1733 /* map a thread list to a CPU set */
1734#ifdef USE_CPU_AFFINITY
1735#ifdef USE_THREAD
1736 unsigned long proc, thread, cpus;
1737 int i, j;
1738
1739 proc = parse_process_number(args[1]);
1740 thread = parse_process_number(args[2]);
1741 if (!proc || !thread || !*args[3]) {
1742 Alert("parsing [%s:%d]: %s expects a process number "
1743 "('all', 'odd', 'even', or a number from 1 to %d), "
1744 " followed by a thread number using the same format, "
1745 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
1746 file, linenum, args[0], LONGBITS, LONGBITS - 1);
1747 err_code |= ERR_ALERT | ERR_FATAL;
1748 goto out;
1749 }
1750 if (parse_cpu_set((const char **)args+3, &cpus, &errmsg)) {
1751 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755 for (i = 0; i < LONGBITS; i++)
1756 if (proc & (1UL << i)) {
1757 for (j = 0; j < LONGBITS; j++)
1758 if (thread & (1UL << j))
1759 global.thread_map[i][j] = cpus;
1760 }
1761#else
1762 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_THREAD.\n",
1763 file, linenum, args[0]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766#endif /* ! USE_THREAD*/
1767#else
1768 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1769 file, linenum, args[0]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772#endif /* ! USE_CPU_AFFINITY */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001773 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001774 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1775 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1776 goto out;
1777
1778 if (*(args[2]) == 0) {
1779 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783
1784 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1785 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1786 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1787 err_code |= ERR_ALERT | ERR_FATAL;
1788 goto out;
1789 }
1790 }
1791 else if (!strcmp(args[0], "unsetenv")) {
1792 int arg;
1793
1794 if (*(args[1]) == 0) {
1795 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
1798 }
1799
1800 for (arg = 1; *args[arg]; arg++) {
1801 if (unsetenv(args[arg]) != 0) {
1802 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806 }
1807 }
1808 else if (!strcmp(args[0], "resetenv")) {
1809 extern char **environ;
1810 char **env = environ;
1811
1812 /* args contain variable names to keep, one per argument */
1813 while (*env) {
1814 int arg;
1815
1816 /* look for current variable in among all those we want to keep */
1817 for (arg = 1; *args[arg]; arg++) {
1818 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1819 (*env)[strlen(args[arg])] == '=')
1820 break;
1821 }
1822
1823 /* delete this variable */
1824 if (!*args[arg]) {
1825 char *delim = strchr(*env, '=');
1826
1827 if (!delim || delim - *env >= trash.size) {
1828 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831 }
1832
1833 memcpy(trash.str, *env, delim - *env);
1834 trash.str[delim - *env] = 0;
1835
1836 if (unsetenv(trash.str) != 0) {
1837 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1838 err_code |= ERR_ALERT | ERR_FATAL;
1839 goto out;
1840 }
1841 }
1842 else
1843 env++;
1844 }
1845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001847 struct cfg_kw_list *kwl;
1848 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001849 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001850
1851 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1852 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1853 if (kwl->kw[index].section != CFG_GLOBAL)
1854 continue;
1855 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001856 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001857 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001858 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001859 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001860 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001861 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001862 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001863 err_code |= ERR_WARN;
1864 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001865 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001866 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001867 }
1868 }
1869 }
1870
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001872 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001874
Willy Tarreau058e9072009-07-20 09:30:05 +02001875 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001876 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001877 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001878}
1879
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001880void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001882 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 defproxy.mode = PR_MODE_TCP;
1884 defproxy.state = PR_STNEW;
1885 defproxy.maxconn = cfg_maxpconn;
1886 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001887 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001888 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001889
Simon Horman66183002013-02-23 10:16:43 +09001890 defproxy.defsrv.check.inter = DEF_CHKINTR;
1891 defproxy.defsrv.check.fastinter = 0;
1892 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001893 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1894 defproxy.defsrv.agent.fastinter = 0;
1895 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001896 defproxy.defsrv.check.rise = DEF_RISETIME;
1897 defproxy.defsrv.check.fall = DEF_FALLTIME;
1898 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1899 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001900 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001901 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001902 defproxy.defsrv.maxqueue = 0;
1903 defproxy.defsrv.minconn = 0;
1904 defproxy.defsrv.maxconn = 0;
1905 defproxy.defsrv.slowstart = 0;
1906 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1907 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1908 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001909
1910 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001911 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912}
1913
Willy Tarreauade5ec42010-01-28 19:33:49 +01001914
Willy Tarreau63af98d2014-05-18 08:11:41 +02001915/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1916 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1917 * ERR_FATAL in case of error.
1918 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001919static int create_cond_regex_rule(const char *file, int line,
1920 struct proxy *px, int dir, int action, int flags,
1921 const char *cmd, const char *reg, const char *repl,
1922 const char **cond_start)
1923{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001924 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001925 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001926 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001927 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001928 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001929 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001930 int cs;
1931 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001932
1933 if (px == &defproxy) {
1934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001935 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001936 goto err;
1937 }
1938
1939 if (*reg == 0) {
1940 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001941 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001942 goto err;
1943 }
1944
Christopher Faulet898566e2016-10-26 11:06:28 +02001945 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001946 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001947
Willy Tarreau5321c422010-01-28 20:35:13 +01001948 if (cond_start &&
1949 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02001950 if ((cond = build_acl_cond(file, line, &px->acl, px, cond_start, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001951 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1952 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001953 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001954 goto err;
1955 }
1956 }
1957 else if (cond_start && **cond_start) {
1958 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1959 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001960 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001961 goto err;
1962 }
1963
Willy Tarreau63af98d2014-05-18 08:11:41 +02001964 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001965 (dir == SMP_OPT_DIR_REQ) ?
1966 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1967 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1968 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001969
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001970 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001971 if (!preg) {
1972 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001973 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001974 goto err;
1975 }
1976
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001977 cs = !(flags & REG_ICASE);
1978 cap = !(flags & REG_NOSUB);
1979 error = NULL;
1980 if (!regex_comp(reg, preg, cs, cap, &error)) {
1981 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1982 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001983 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001984 goto err;
1985 }
1986
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001987 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001988 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001989 if (repl && err) {
1990 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1991 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001992 ret_code |= ERR_ALERT | ERR_FATAL;
1993 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001994 }
1995
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001996 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001997 ret_code |= ERR_WARN;
1998
1999 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002000
Willy Tarreau63af98d2014-05-18 08:11:41 +02002001 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002002 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002003 err:
2004 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002005 free(errmsg);
2006 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002007}
2008
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009/*
William Lallemand51097192015-04-14 16:35:22 +02002010 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002011 * Returns the error code, 0 if OK, or any combination of :
2012 * - ERR_ABORT: must abort ASAP
2013 * - ERR_FATAL: we can continue parsing but not start the service
2014 * - ERR_WARN: a warning has been emitted
2015 * - ERR_ALERT: an alert has been emitted
2016 * Only the two first ones can stop processing, the two others are just
2017 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002019int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2020{
2021 static struct peers *curpeers = NULL;
2022 struct peer *newpeer = NULL;
2023 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002024 struct bind_conf *bind_conf;
2025 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002026 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002027 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002028
2029 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002030 if (!*args[1]) {
2031 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002032 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002033 goto out;
2034 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002035
William Lallemand6e62fb62015-04-28 16:55:23 +02002036 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2037 goto out;
2038
Emeric Brun32da3c42010-09-23 18:39:19 +02002039 err = invalid_char(args[1]);
2040 if (err) {
2041 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2042 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002043 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002044 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002045 }
2046
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002047 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002048 /*
2049 * If there are two proxies with the same name only following
2050 * combinations are allowed:
2051 */
2052 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002053 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 +02002054 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002055 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002056 }
2057 }
2058
Vincent Bernat02779b62016-04-03 13:48:43 +02002059 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002060 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2061 err_code |= ERR_ALERT | ERR_ABORT;
2062 goto out;
2063 }
2064
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002065 curpeers->next = cfg_peers;
2066 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002067 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002068 curpeers->conf.line = linenum;
2069 curpeers->last_change = now.tv_sec;
2070 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002071 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002072 }
2073 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002074 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002075 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002076 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002077
2078 if (!*args[2]) {
2079 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2080 file, linenum, args[0]);
2081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
2083 }
2084
2085 err = invalid_char(args[1]);
2086 if (err) {
2087 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2088 file, linenum, *err, args[1]);
2089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
2091 }
2092
Vincent Bernat02779b62016-04-03 13:48:43 +02002093 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002094 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2095 err_code |= ERR_ALERT | ERR_ABORT;
2096 goto out;
2097 }
2098
2099 /* the peers are linked backwards first */
2100 curpeers->count++;
2101 newpeer->next = curpeers->remote;
2102 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002103 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002104 newpeer->conf.line = linenum;
2105
2106 newpeer->last_change = now.tv_sec;
2107 newpeer->id = strdup(args[1]);
2108
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002109 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002110 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002111 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002114 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002115
2116 proto = protocol_by_family(sk->ss_family);
2117 if (!proto || !proto->connect) {
2118 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2119 file, linenum, args[0], args[1]);
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002123
2124 if (port1 != port2) {
2125 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2126 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
2129 }
2130
Willy Tarreau2aa38802013-02-20 19:20:59 +01002131 if (!port1) {
2132 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2133 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
2136 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002137
Emeric Brun32da3c42010-09-23 18:39:19 +02002138 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002139 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002140 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002141 newpeer->sock_init_arg = NULL;
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002142 HA_SPIN_INIT(&newpeer->lock);
Willy Tarreau26d8c592012-05-07 18:12:14 +02002143
Emeric Brun32da3c42010-09-23 18:39:19 +02002144 if (strcmp(newpeer->id, localpeer) == 0) {
2145 /* Current is local peer, it define a frontend */
2146 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002147 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002148
2149 if (!curpeers->peers_fe) {
2150 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2151 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2152 err_code |= ERR_ALERT | ERR_ABORT;
2153 goto out;
2154 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002155
Willy Tarreau237250c2011-07-29 01:49:03 +02002156 init_new_proxy(curpeers->peers_fe);
2157 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002159 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2160 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002161 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002162
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002163 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002164
Willy Tarreau902636f2013-03-10 19:44:48 +01002165 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2166 if (errmsg && *errmsg) {
2167 indent_msg(&errmsg, 2);
2168 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002169 }
2170 else
2171 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2172 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002173 err_code |= ERR_FATAL;
2174 goto out;
2175 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002176
2177 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002178 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002179 l->maxconn = curpeers->peers_fe->maxconn;
2180 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002181 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002182 l->analysers |= curpeers->peers_fe->fe_req_ana;
2183 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002184 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2185 global.maxsock += l->maxconn;
2186 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002187 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002188 else {
2189 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2190 file, linenum, args[0], args[1],
2191 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2192 err_code |= ERR_FATAL;
2193 goto out;
2194 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002195 }
2196 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002197 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2198 curpeers->state = PR_STSTOPPED;
2199 }
2200 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2201 curpeers->state = PR_STNEW;
2202 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002203 else if (*args[0] != 0) {
2204 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208
2209out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002210 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002211 return err_code;
2212}
2213
Baptiste Assmann325137d2015-04-13 23:40:55 +02002214/*
2215 * Parse a <resolvers> section.
2216 * Returns the error code, 0 if OK, or any combination of :
2217 * - ERR_ABORT: must abort ASAP
2218 * - ERR_FATAL: we can continue parsing but not start the service
2219 * - ERR_WARN: a warning has been emitted
2220 * - ERR_ALERT: an alert has been emitted
2221 * Only the two first ones can stop processing, the two others are just
2222 * indicators.
2223 */
2224int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2225{
2226 static struct dns_resolvers *curr_resolvers = NULL;
2227 struct dns_nameserver *newnameserver = NULL;
2228 const char *err;
2229 int err_code = 0;
2230 char *errmsg = NULL;
2231
2232 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2233 if (!*args[1]) {
2234 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2235 err_code |= ERR_ALERT | ERR_ABORT;
2236 goto out;
2237 }
2238
2239 err = invalid_char(args[1]);
2240 if (err) {
2241 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2242 file, linenum, *err, args[0], args[1]);
2243 err_code |= ERR_ALERT | ERR_ABORT;
2244 goto out;
2245 }
2246
2247 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2248 /* Error if two resolvers owns the same name */
2249 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2250 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2251 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2252 err_code |= ERR_ALERT | ERR_ABORT;
2253 }
2254 }
2255
Vincent Bernat02779b62016-04-03 13:48:43 +02002256 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002257 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2258 err_code |= ERR_ALERT | ERR_ABORT;
2259 goto out;
2260 }
2261
2262 /* default values */
2263 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2264 curr_resolvers->conf.file = strdup(file);
2265 curr_resolvers->conf.line = linenum;
2266 curr_resolvers->id = strdup(args[1]);
2267 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002268 /* default maximum response size */
2269 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002270 /* default hold period for nx, other, refuse and timeout is 30s */
2271 curr_resolvers->hold.nx = 30000;
2272 curr_resolvers->hold.other = 30000;
2273 curr_resolvers->hold.refused = 30000;
2274 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002275 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002276 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002277 curr_resolvers->hold.valid = 10000;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002278 curr_resolvers->timeout.resolve = 1000;
2279 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002280 curr_resolvers->resolve_retries = 3;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002281 curr_resolvers->nb_nameservers = 0;
2282 LIST_INIT(&curr_resolvers->nameservers);
2283 LIST_INIT(&curr_resolvers->resolutions.curr);
2284 LIST_INIT(&curr_resolvers->resolutions.wait);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002285 HA_SPIN_INIT(&curr_resolvers->lock);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002286 }
2287 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2288 struct sockaddr_storage *sk;
2289 int port1, port2;
2290 struct protocol *proto;
2291
2292 if (!*args[2]) {
2293 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2294 file, linenum, args[0]);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298
2299 err = invalid_char(args[1]);
2300 if (err) {
2301 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2302 file, linenum, *err, args[1]);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306
Christopher Faulet67957bd2017-09-27 11:00:59 +02002307 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002308 /* Error if two resolvers owns the same name */
2309 if (strcmp(newnameserver->id, args[1]) == 0) {
2310 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2311 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2312 err_code |= ERR_ALERT | ERR_FATAL;
2313 }
2314 }
2315
Vincent Bernat02779b62016-04-03 13:48:43 +02002316 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002317 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2318 err_code |= ERR_ALERT | ERR_ABORT;
2319 goto out;
2320 }
2321
2322 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002323 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002324 newnameserver->resolvers = curr_resolvers;
2325 newnameserver->conf.file = strdup(file);
2326 newnameserver->conf.line = linenum;
2327 newnameserver->id = strdup(args[1]);
2328
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002329 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002330 if (!sk) {
2331 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335
2336 proto = protocol_by_family(sk->ss_family);
2337 if (!proto || !proto->connect) {
2338 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2339 file, linenum, args[0], args[1]);
2340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
2343
2344 if (port1 != port2) {
2345 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2346 file, linenum, args[0], args[1], args[2]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002351 if (!port1 && !port2) {
2352 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2353 file, linenum, args[0], args[1]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357
Baptiste Assmann325137d2015-04-13 23:40:55 +02002358 newnameserver->addr = *sk;
2359 }
2360 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2361 const char *res;
2362 unsigned int time;
2363
2364 if (!*args[2]) {
2365 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2366 file, linenum, args[0]);
2367 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
2370 }
2371 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2372 if (res) {
2373 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2374 file, linenum, *res, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002378 if (strcmp(args[1], "nx") == 0)
2379 curr_resolvers->hold.nx = time;
2380 else if (strcmp(args[1], "other") == 0)
2381 curr_resolvers->hold.other = time;
2382 else if (strcmp(args[1], "refused") == 0)
2383 curr_resolvers->hold.refused = time;
2384 else if (strcmp(args[1], "timeout") == 0)
2385 curr_resolvers->hold.timeout = time;
2386 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002387 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002388 else if (strcmp(args[1], "obsolete") == 0)
2389 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002390 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002391 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002392 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
2395 }
2396
2397 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002398 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002399 int i = 0;
2400
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002401 if (!*args[1]) {
2402 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2403 file, linenum, args[0]);
2404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
2406 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002407
2408 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002409 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2410 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2411 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
2414 }
2415
2416 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002417 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002418 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002419 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2420 file, linenum, args[0]);
2421 err_code |= ERR_WARN;
2422 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002423 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002424 else if (strcmp(args[0], "resolve_retries") == 0) {
2425 if (!*args[1]) {
2426 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2427 file, linenum, args[0]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431 curr_resolvers->resolve_retries = atoi(args[1]);
2432 }
2433 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002434 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002435 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002436 file, linenum, args[0]);
2437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
2439 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002440 else if (strcmp(args[1], "retry") == 0 ||
2441 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002442 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002443 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002444
2445 if (!*args[2]) {
2446 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2447 file, linenum, args[0], args[1]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002451 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002452 if (res) {
2453 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2454 file, linenum, *res, args[0], args[1]);
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002458 if (args[1][2] == 't')
2459 curr_resolvers->timeout.retry = tout;
2460 else
2461 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002462 }
2463 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002464 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002465 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002469 } /* neither "nameserver" nor "resolvers" */
2470 else if (*args[0] != 0) {
2471 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
2474 }
2475
2476 out:
2477 free(errmsg);
2478 return err_code;
2479}
Simon Horman0d16a402015-01-30 11:22:58 +09002480
2481/*
William Lallemand51097192015-04-14 16:35:22 +02002482 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002483 * Returns the error code, 0 if OK, or any combination of :
2484 * - ERR_ABORT: must abort ASAP
2485 * - ERR_FATAL: we can continue parsing but not start the service
2486 * - ERR_WARN: a warning has been emitted
2487 * - ERR_ALERT: an alert has been emitted
2488 * Only the two first ones can stop processing, the two others are just
2489 * indicators.
2490 */
2491int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2492{
2493 static struct mailers *curmailers = NULL;
2494 struct mailer *newmailer = NULL;
2495 const char *err;
2496 int err_code = 0;
2497 char *errmsg = NULL;
2498
2499 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2500 if (!*args[1]) {
2501 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2502 err_code |= ERR_ALERT | ERR_ABORT;
2503 goto out;
2504 }
2505
2506 err = invalid_char(args[1]);
2507 if (err) {
2508 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2509 file, linenum, *err, args[0], args[1]);
2510 err_code |= ERR_ALERT | ERR_ABORT;
2511 goto out;
2512 }
2513
2514 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2515 /*
2516 * If there are two proxies with the same name only following
2517 * combinations are allowed:
2518 */
2519 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002520 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 +09002521 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002523 }
2524 }
2525
Vincent Bernat02779b62016-04-03 13:48:43 +02002526 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002527 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2528 err_code |= ERR_ALERT | ERR_ABORT;
2529 goto out;
2530 }
2531
2532 curmailers->next = mailers;
2533 mailers = curmailers;
2534 curmailers->conf.file = strdup(file);
2535 curmailers->conf.line = linenum;
2536 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002537 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2538 * But need enough time so that timeouts don't occur
2539 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002540 }
2541 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2542 struct sockaddr_storage *sk;
2543 int port1, port2;
2544 struct protocol *proto;
2545
2546 if (!*args[2]) {
2547 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2548 file, linenum, args[0]);
2549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
2551 }
2552
2553 err = invalid_char(args[1]);
2554 if (err) {
2555 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2556 file, linenum, *err, args[1]);
2557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
2559 }
2560
Vincent Bernat02779b62016-04-03 13:48:43 +02002561 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002562 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2563 err_code |= ERR_ALERT | ERR_ABORT;
2564 goto out;
2565 }
2566
2567 /* the mailers are linked backwards first */
2568 curmailers->count++;
2569 newmailer->next = curmailers->mailer_list;
2570 curmailers->mailer_list = newmailer;
2571 newmailer->mailers = curmailers;
2572 newmailer->conf.file = strdup(file);
2573 newmailer->conf.line = linenum;
2574
2575 newmailer->id = strdup(args[1]);
2576
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002577 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002578 if (!sk) {
2579 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
2582 }
2583
2584 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002585 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2586 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002587 file, linenum, args[0], args[1]);
2588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
2590 }
2591
2592 if (port1 != port2) {
2593 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2594 file, linenum, args[0], args[1], args[2]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
2599 if (!port1) {
2600 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2601 file, linenum, args[0], args[1], args[2]);
2602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
2604 }
2605
2606 newmailer->addr = *sk;
2607 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002608 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002609 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002610 }
2611 else if (strcmp(args[0], "timeout") == 0) {
2612 if (!*args[1]) {
2613 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2614 file, linenum, args[0]);
2615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
2617 }
2618 else if (strcmp(args[1], "mail") == 0) {
2619 const char *res;
2620 unsigned int timeout_mail;
2621 if (!*args[2]) {
2622 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2623 file, linenum, args[0], args[1]);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2628 if (res) {
2629 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2630 file, linenum, *res, args[0]);
2631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
2633 }
2634 if (timeout_mail <= 0) {
2635 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
2638 }
2639 curmailers->timeout.mail = timeout_mail;
2640 } else {
2641 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2642 file, linenum, args[0], args[1]);
2643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
2645 }
2646 }
Simon Horman0d16a402015-01-30 11:22:58 +09002647 else if (*args[0] != 0) {
2648 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651 }
2652
2653out:
2654 free(errmsg);
2655 return err_code;
2656}
2657
Simon Horman9dc49962015-01-30 11:22:59 +09002658static void free_email_alert(struct proxy *p)
2659{
2660 free(p->email_alert.mailers.name);
2661 p->email_alert.mailers.name = NULL;
2662 free(p->email_alert.from);
2663 p->email_alert.from = NULL;
2664 free(p->email_alert.to);
2665 p->email_alert.to = NULL;
2666 free(p->email_alert.myhostname);
2667 p->email_alert.myhostname = NULL;
2668}
2669
Willy Tarreau3842f002009-06-14 11:39:52 +02002670int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671{
2672 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002673 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002674 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002675 int rc;
2676 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002677 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002678 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002679 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002680 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002681 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683 if (!strcmp(args[0], "listen"))
2684 rc = PR_CAP_LISTEN;
2685 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002686 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002687 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002688 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002689 else
2690 rc = PR_CAP_NONE;
2691
2692 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 if (!*args[1]) {
2694 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002695 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_ABORT;
2698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002700
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002701 err = invalid_char(args[1]);
2702 if (err) {
2703 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2704 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002706 }
2707
Willy Tarreau8f50b682015-05-26 11:45:02 +02002708 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2709 if (curproxy) {
2710 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2711 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2712 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002714 }
2715
Vincent Bernat02779b62016-04-03 13:48:43 +02002716 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_ABORT;
2719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002721
Willy Tarreau97cb7802010-01-03 20:23:58 +01002722 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 curproxy->next = proxy;
2724 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002725 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2726 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002727 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002730 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731
William Lallemand6e62fb62015-04-28 16:55:23 +02002732 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2733 if (curproxy->cap & PR_CAP_FE)
2734 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 }
2737
2738 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002739 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002740 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002741
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002744 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002745 curproxy->no_options = defproxy.no_options;
2746 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002747 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002748 curproxy->except_net = defproxy.except_net;
2749 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002750 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002751 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002753 if (defproxy.fwdfor_hdr_len) {
2754 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2755 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2756 }
2757
Willy Tarreaub86db342009-11-30 11:50:16 +01002758 if (defproxy.orgto_hdr_len) {
2759 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2760 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2761 }
2762
Mark Lamourinec2247f02012-01-04 13:02:01 -05002763 if (defproxy.server_id_hdr_len) {
2764 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2765 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2766 }
2767
Willy Tarreau977b8e42006-12-29 14:19:17 +01002768 if (curproxy->cap & PR_CAP_FE) {
2769 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002770 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002771 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002772
2773 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002774 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2775 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002776
2777 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779
Willy Tarreau977b8e42006-12-29 14:19:17 +01002780 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002781 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002782 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783 curproxy->fullconn = defproxy.fullconn;
2784 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002785 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002786 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002788 if (defproxy.check_req) {
2789 curproxy->check_req = calloc(1, defproxy.check_len);
2790 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2791 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002792 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002794 if (defproxy.expect_str) {
2795 curproxy->expect_str = strdup(defproxy.expect_str);
2796 if (defproxy.expect_regex) {
2797 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002798 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2799 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002800 }
2801 }
2802
Willy Tarreau67402132012-05-31 20:40:20 +02002803 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002804 if (defproxy.cookie_name)
2805 curproxy->cookie_name = strdup(defproxy.cookie_name);
2806 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002807
2808 if (defproxy.dyncookie_key)
2809 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002810 if (defproxy.cookie_domain)
2811 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002812
Willy Tarreau31936852010-10-06 16:59:56 +02002813 if (defproxy.cookie_maxidle)
2814 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2815
2816 if (defproxy.cookie_maxlife)
2817 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2818
Emeric Brun647caf12009-06-30 17:57:00 +02002819 if (defproxy.rdp_cookie_name)
2820 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2821 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2822
Willy Tarreau01732802007-11-01 22:48:15 +01002823 if (defproxy.url_param_name)
2824 curproxy->url_param_name = strdup(defproxy.url_param_name);
2825 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002826
Benoitaffb4812009-03-25 13:02:10 +01002827 if (defproxy.hh_name)
2828 curproxy->hh_name = strdup(defproxy.hh_name);
2829 curproxy->hh_len = defproxy.hh_len;
2830 curproxy->hh_match_domain = defproxy.hh_match_domain;
2831
Willy Tarreauef9a3602012-12-08 22:29:20 +01002832 if (defproxy.conn_src.iface_name)
2833 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2834 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002835 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002836#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002837 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002838#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002839 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002840 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002842 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002843 if (defproxy.capture_name)
2844 curproxy->capture_name = strdup(defproxy.capture_name);
2845 curproxy->capture_namelen = defproxy.capture_namelen;
2846 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848
Willy Tarreau977b8e42006-12-29 14:19:17 +01002849 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002850 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002851 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002852 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002853 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002854 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002855 curproxy->mon_net = defproxy.mon_net;
2856 curproxy->mon_mask = defproxy.mon_mask;
2857 if (defproxy.monitor_uri)
2858 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2859 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002860 if (defproxy.defbe.name)
2861 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002862
2863 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002864 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2865 if (curproxy->conf.logformat_string &&
2866 curproxy->conf.logformat_string != default_http_log_format &&
2867 curproxy->conf.logformat_string != default_tcp_log_format &&
2868 curproxy->conf.logformat_string != clf_http_log_format)
2869 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2870
2871 if (defproxy.conf.lfs_file) {
2872 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2873 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2874 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002875
2876 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2877 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2878 if (curproxy->conf.logformat_sd_string &&
2879 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2880 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2881
2882 if (defproxy.conf.lfsd_file) {
2883 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2884 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2885 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002886 }
2887
2888 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002889 curproxy->timeout.connect = defproxy.timeout.connect;
2890 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002891 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002892 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002893 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002894 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002895 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002896 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002897 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002898 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899 }
2900
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002902 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002903
2904 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002905 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002906 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002907 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002908 LIST_INIT(&node->list);
2909 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2910 }
2911
Willy Tarreau62a61232013-04-12 18:13:46 +02002912 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2913 if (curproxy->conf.uniqueid_format_string)
2914 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2915
Dragan Dosen43885c72015-10-01 13:18:13 +02002916 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002917
Willy Tarreau62a61232013-04-12 18:13:46 +02002918 if (defproxy.conf.uif_file) {
2919 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2920 curproxy->conf.uif_line = defproxy.conf.uif_line;
2921 }
William Lallemanda73203e2012-03-12 12:48:57 +01002922
2923 /* copy default header unique id */
2924 if (defproxy.header_unique_id)
2925 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2926
William Lallemand82fe75c2012-10-23 10:25:10 +02002927 /* default compression options */
2928 if (defproxy.comp != NULL) {
2929 curproxy->comp = calloc(1, sizeof(struct comp));
2930 curproxy->comp->algos = defproxy.comp->algos;
2931 curproxy->comp->types = defproxy.comp->types;
2932 }
2933
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002935 curproxy->conf.used_listener_id = EB_ROOT;
2936 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002937
Simon Horman98637e52014-06-20 12:30:16 +09002938 if (defproxy.check_path)
2939 curproxy->check_path = strdup(defproxy.check_path);
2940 if (defproxy.check_command)
2941 curproxy->check_command = strdup(defproxy.check_command);
2942
Simon Horman9dc49962015-01-30 11:22:59 +09002943 if (defproxy.email_alert.mailers.name)
2944 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2945 if (defproxy.email_alert.from)
2946 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2947 if (defproxy.email_alert.to)
2948 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2949 if (defproxy.email_alert.myhostname)
2950 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002951 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002952 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002953
Willy Tarreau93893792009-07-23 13:19:11 +02002954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 }
2956 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2957 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002958 /* FIXME-20070101: we should do this too at the end of the
2959 * config parsing to free all default values.
2960 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002961 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2962 err_code |= ERR_ABORT;
2963 goto out;
2964 }
2965
Willy Tarreaua534fea2008-08-03 12:19:50 +02002966 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002967 free(defproxy.check_command);
2968 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002969 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002970 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002971 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002972 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002973 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002974 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002975 free(defproxy.capture_name);
2976 free(defproxy.monitor_uri);
2977 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002978 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002979 free(defproxy.fwdfor_hdr_name);
2980 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002981 free(defproxy.orgto_hdr_name);
2982 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002983 free(defproxy.server_id_hdr_name);
2984 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002985 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002986 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002987 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002988 free(defproxy.expect_regex);
2989 defproxy.expect_regex = NULL;
2990 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002991
Willy Tarreau62a61232013-04-12 18:13:46 +02002992 if (defproxy.conf.logformat_string != default_http_log_format &&
2993 defproxy.conf.logformat_string != default_tcp_log_format &&
2994 defproxy.conf.logformat_string != clf_http_log_format)
2995 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002996
Willy Tarreau62a61232013-04-12 18:13:46 +02002997 free(defproxy.conf.uniqueid_format_string);
2998 free(defproxy.conf.lfs_file);
2999 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003000 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003001 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003002
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003003 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3004 free(defproxy.conf.logformat_sd_string);
3005 free(defproxy.conf.lfsd_file);
3006
Willy Tarreaua534fea2008-08-03 12:19:50 +02003007 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003008 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003009
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 /* we cannot free uri_auth because it might already be used */
3011 init_default_instance();
3012 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003013 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3014 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003015 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 }
3018 else if (curproxy == NULL) {
3019 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003023
3024 /* update the current file and line being parsed */
3025 curproxy->conf.args.file = curproxy->conf.file;
3026 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003027
3028 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02003029 if (!strcmp(args[0], "server") ||
3030 !strcmp(args[0], "default-server") ||
3031 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02003032 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3033 if (err_code & ERR_FATAL)
3034 goto out;
3035 }
3036 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003037 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003038 int cur_arg;
3039
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 if (curproxy == &defproxy) {
3041 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003045 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047
Willy Tarreau24709282013-03-10 21:32:12 +01003048 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003049 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003054
Willy Tarreaua261e9b2016-12-22 20:44:00 +01003055 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003056
3057 /* use default settings for unix sockets */
3058 bind_conf->ux.uid = global.unix_bind.ux.uid;
3059 bind_conf->ux.gid = global.unix_bind.ux.gid;
3060 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003061
3062 /* NOTE: the following line might create several listeners if there
3063 * are comma-separated IPs or port ranges. So all further processing
3064 * will have to be applied to all listeners created after last_listen.
3065 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003066 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3067 if (errmsg && *errmsg) {
3068 indent_msg(&errmsg, 2);
3069 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003070 }
3071 else
3072 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3073 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003077
Willy Tarreau4348fad2012-09-20 16:48:07 +02003078 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3079 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003080 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003081 }
3082
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003083 cur_arg = 2;
3084 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003085 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003086 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003087 char *err;
3088
Willy Tarreau26982662012-09-12 23:17:10 +02003089 kw = bind_find_kw(args[cur_arg]);
3090 if (kw) {
3091 char *err = NULL;
3092 int code;
3093
3094 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003095 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3096 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003097 cur_arg += 1 + kw->skip ;
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101
Willy Tarreau4348fad2012-09-20 16:48:07 +02003102 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003103 err_code |= code;
3104
3105 if (code) {
3106 if (err && *err) {
3107 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003108 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003109 }
3110 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003111 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3112 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003113 if (code & ERR_FATAL) {
3114 free(err);
3115 cur_arg += 1 + kw->skip;
3116 goto out;
3117 }
3118 }
3119 free(err);
3120 cur_arg += 1 + kw->skip;
3121 continue;
3122 }
3123
Willy Tarreau8638f482012-09-18 18:01:17 +02003124 err = NULL;
3125 if (!bind_dumped) {
3126 bind_dump_kws(&err);
3127 indent_msg(&err, 4);
3128 bind_dumped = 1;
3129 }
3130
3131 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3132 file, linenum, args[0], args[1], args[cur_arg],
3133 err ? " Registered keywords :" : "", err ? err : "");
3134 free(err);
3135
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003138 }
Willy Tarreau93893792009-07-23 13:19:11 +02003139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 }
3141 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003142 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3144 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003148 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003150
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 /* flush useless bits */
3152 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003155 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003156 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003158
William Lallemanddf1425a2015-04-28 20:17:49 +02003159 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3160 goto out;
3161
Willy Tarreau1c47f852006-07-09 08:22:27 +02003162 if (!*args[1]) {
3163 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003167 }
3168
Willy Tarreaua534fea2008-08-03 12:19:50 +02003169 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003170 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003171 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003172 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003173 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3174
Willy Tarreau93893792009-07-23 13:19:11 +02003175 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003178 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3179 goto out;
3180
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3182 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3183 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3184 else {
3185 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
3189 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003190 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003191 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003192
3193 if (curproxy == &defproxy) {
3194 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3195 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003198 }
3199
William Lallemanddf1425a2015-04-28 20:17:49 +02003200 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3201 goto out;
3202
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003203 if (!*args[1]) {
3204 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003208 }
3209
3210 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003211 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003212 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003213
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003214 if (curproxy->uuid <= 0) {
3215 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003216 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003219 }
3220
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003221 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3222 if (node) {
3223 struct proxy *target = container_of(node, struct proxy, conf.id);
3224 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3225 file, linenum, proxy_type_str(curproxy), curproxy->id,
3226 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
3229 }
3230 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003231 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003232 else if (!strcmp(args[0], "description")) {
3233 int i, len=0;
3234 char *d;
3235
Cyril Bonté99ed3272010-01-24 23:29:44 +01003236 if (curproxy == &defproxy) {
3237 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3238 file, linenum, args[0]);
3239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
3241 }
3242
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003243 if (!*args[1]) {
3244 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3245 file, linenum, args[0]);
3246 return -1;
3247 }
3248
Willy Tarreau348acfe2014-04-14 15:00:39 +02003249 for (i = 1; *args[i]; i++)
3250 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003251
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003252 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003253 curproxy->desc = d;
3254
Willy Tarreau348acfe2014-04-14 15:00:39 +02003255 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3256 for (i = 2; *args[i]; i++)
3257 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003258
3259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003261 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 curproxy->state = PR_STSTOPPED;
3264 }
3265 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003266 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 curproxy->state = PR_STNEW;
3269 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003270 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3271 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003272 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003273
3274 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003275 unsigned int low, high;
3276
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003277 if (strcmp(args[cur_arg], "all") == 0) {
3278 set = 0;
3279 break;
3280 }
3281 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003282 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003283 }
3284 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003285 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003286 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003287 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003288 char *dash = strchr(args[cur_arg], '-');
3289
3290 low = high = str2uic(args[cur_arg]);
3291 if (dash)
3292 high = str2uic(dash + 1);
3293
3294 if (high < low) {
3295 unsigned int swap = low;
3296 low = high;
3297 high = swap;
3298 }
3299
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003300 if (low < 1 || high > LONGBITS) {
3301 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3302 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003305 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003306 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003307 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003308 }
3309 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003310 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3311 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003314 }
3315 cur_arg++;
3316 }
3317 curproxy->bind_proc = set;
3318 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003319 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003320 if (curproxy == &defproxy) {
3321 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003324 }
3325
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003326 err = invalid_char(args[1]);
3327 if (err) {
3328 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3329 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003331 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003332 }
3333
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003334 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003335 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3336 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003339 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003340 }
3341 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3342
3343 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3344 err_code |= ERR_WARN;
3345
3346 if (*(args[1]) == 0) {
3347 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3348 file, linenum, args[0]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352 free(curproxy->dyncookie_key);
3353 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3356 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357
Willy Tarreau977b8e42006-12-29 14:19:17 +01003358 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003360
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 if (*(args[1]) == 0) {
3362 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3363 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003367
Willy Tarreau67402132012-05-31 20:40:20 +02003368 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003369 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003370 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003371 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 curproxy->cookie_name = strdup(args[1]);
3373 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003374
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 cur_arg = 2;
3376 while (*(args[cur_arg])) {
3377 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003378 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 }
3380 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003381 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }
3383 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003384 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
3386 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003387 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 }
3389 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003390 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003392 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003393 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003396 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003398 else if (!strcmp(args[cur_arg], "httponly")) {
3399 curproxy->ck_opts |= PR_CK_HTTPONLY;
3400 }
3401 else if (!strcmp(args[cur_arg], "secure")) {
3402 curproxy->ck_opts |= PR_CK_SECURE;
3403 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003404 else if (!strcmp(args[cur_arg], "domain")) {
3405 if (!*args[cur_arg + 1]) {
3406 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3407 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003410 }
3411
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003412 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003413 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003414 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3415 " dots nor does not start with a dot."
3416 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003417 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003418 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003419 }
3420
3421 err = invalid_domainchar(args[cur_arg + 1]);
3422 if (err) {
3423 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3424 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003427 }
3428
Willy Tarreau68a897b2009-12-03 23:28:34 +01003429 if (!curproxy->cookie_domain) {
3430 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3431 } else {
3432 /* one domain was already specified, add another one by
3433 * building the string which will be returned along with
3434 * the cookie.
3435 */
3436 char *new_ptr;
3437 int new_len = strlen(curproxy->cookie_domain) +
3438 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3439 new_ptr = malloc(new_len);
3440 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3441 free(curproxy->cookie_domain);
3442 curproxy->cookie_domain = new_ptr;
3443 }
Willy Tarreau31936852010-10-06 16:59:56 +02003444 cur_arg++;
3445 }
3446 else if (!strcmp(args[cur_arg], "maxidle")) {
3447 unsigned int maxidle;
3448 const char *res;
3449
3450 if (!*args[cur_arg + 1]) {
3451 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3452 file, linenum, args[cur_arg]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456
3457 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3458 if (res) {
3459 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3460 file, linenum, *res, args[cur_arg]);
3461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464 curproxy->cookie_maxidle = maxidle;
3465 cur_arg++;
3466 }
3467 else if (!strcmp(args[cur_arg], "maxlife")) {
3468 unsigned int maxlife;
3469 const char *res;
3470
3471 if (!*args[cur_arg + 1]) {
3472 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3473 file, linenum, args[cur_arg]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
3477
3478 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3479 if (res) {
3480 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3481 file, linenum, *res, args[cur_arg]);
3482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
3484 }
3485 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003486 cur_arg++;
3487 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003488 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003489
3490 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3491 err_code |= ERR_WARN;
3492 curproxy->ck_opts |= PR_CK_DYNAMIC;
3493 }
3494
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003496 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 +02003497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 }
3501 cur_arg++;
3502 }
Willy Tarreau67402132012-05-31 20:40:20 +02003503 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 }
3508
Willy Tarreau67402132012-05-31 20:40:20 +02003509 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3511 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003514
Willy Tarreau67402132012-05-31 20:40:20 +02003515 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003516 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3517 file, linenum);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003521 else if (!strcmp(args[0], "email-alert")) {
3522 if (*(args[1]) == 0) {
3523 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3524 file, linenum, args[0]);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
3527 }
3528
3529 if (!strcmp(args[1], "from")) {
3530 if (*(args[1]) == 0) {
3531 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3532 file, linenum, args[1]);
3533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
3535 }
3536 free(curproxy->email_alert.from);
3537 curproxy->email_alert.from = strdup(args[2]);
3538 }
3539 else if (!strcmp(args[1], "mailers")) {
3540 if (*(args[1]) == 0) {
3541 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3542 file, linenum, args[1]);
3543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
3545 }
3546 free(curproxy->email_alert.mailers.name);
3547 curproxy->email_alert.mailers.name = strdup(args[2]);
3548 }
3549 else if (!strcmp(args[1], "myhostname")) {
3550 if (*(args[1]) == 0) {
3551 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3552 file, linenum, args[1]);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
3556 free(curproxy->email_alert.myhostname);
3557 curproxy->email_alert.myhostname = strdup(args[2]);
3558 }
Simon Horman64e34162015-02-06 11:11:57 +09003559 else if (!strcmp(args[1], "level")) {
3560 curproxy->email_alert.level = get_log_level(args[2]);
3561 if (curproxy->email_alert.level < 0) {
3562 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3563 file, linenum, args[1], args[2]);
3564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
3566 }
3567 }
Simon Horman9dc49962015-01-30 11:22:59 +09003568 else if (!strcmp(args[1], "to")) {
3569 if (*(args[1]) == 0) {
3570 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3571 file, linenum, args[1]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
3575 free(curproxy->email_alert.to);
3576 curproxy->email_alert.to = strdup(args[2]);
3577 }
3578 else {
3579 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3580 file, linenum, args[1]);
3581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
3583 }
Simon Horman64e34162015-02-06 11:11:57 +09003584 /* Indicate that the email_alert is at least partially configured */
3585 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003586 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003587 else if (!strcmp(args[0], "external-check")) {
3588 if (*(args[1]) == 0) {
3589 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3590 file, linenum, args[0]);
3591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
3593 }
3594
3595 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003596 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003597 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003598 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003599 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3600 file, linenum, args[1]);
3601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
3603 }
3604 free(curproxy->check_command);
3605 curproxy->check_command = strdup(args[2]);
3606 }
3607 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003608 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003609 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003610 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003611 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3612 file, linenum, args[1]);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616 free(curproxy->check_path);
3617 curproxy->check_path = strdup(args[2]);
3618 }
3619 else {
3620 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3621 file, linenum, args[1]);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
3625 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003626 else if (!strcmp(args[0], "persist")) { /* persist */
3627 if (*(args[1]) == 0) {
3628 Alert("parsing [%s:%d] : missing persist method.\n",
3629 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003632 }
3633
3634 if (!strncmp(args[1], "rdp-cookie", 10)) {
3635 curproxy->options2 |= PR_O2_RDPC_PRST;
3636
Emeric Brunb982a3d2010-01-04 15:45:53 +01003637 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003638 const char *beg, *end;
3639
3640 beg = args[1] + 11;
3641 end = strchr(beg, ')');
3642
William Lallemanddf1425a2015-04-28 20:17:49 +02003643 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3644 goto out;
3645
Emeric Brun647caf12009-06-30 17:57:00 +02003646 if (!end || end == beg) {
3647 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3648 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003651 }
3652
3653 free(curproxy->rdp_cookie_name);
3654 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3655 curproxy->rdp_cookie_len = end-beg;
3656 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003657 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003658 free(curproxy->rdp_cookie_name);
3659 curproxy->rdp_cookie_name = strdup("msts");
3660 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3661 }
3662 else { /* syntax */
3663 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3664 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003667 }
3668 }
3669 else {
3670 Alert("parsing [%s:%d] : unknown persist method.\n",
3671 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003674 }
3675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003677 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003681 else if (!strcmp(args[0], "load-server-state-from-file")) {
3682 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3683 err_code |= ERR_WARN;
3684 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3685 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3686 }
3687 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3688 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3689 }
3690 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3691 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3692 }
3693 else {
3694 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3695 file, linenum, args[0], args[1]);
3696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
3698 }
3699 }
3700 else if (!strcmp(args[0], "server-state-file-name")) {
3701 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3702 err_code |= ERR_WARN;
3703 if (*(args[1]) == 0) {
3704 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3705 file, linenum, args[0]);
3706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
3708 }
3709 else if (!strcmp(args[1], "use-backend-name"))
3710 curproxy->server_state_file_name = strdup(curproxy->id);
3711 else
3712 curproxy->server_state_file_name = strdup(args[1]);
3713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003715 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003717
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003719 if (curproxy == &defproxy) {
3720 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
3723 }
3724
William Lallemand1a748ae2015-05-19 16:37:23 +02003725 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3726 goto out;
3727
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 if (*(args[4]) == 0) {
3729 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3730 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003733 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003734 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 curproxy->capture_name = strdup(args[2]);
3736 curproxy->capture_namelen = strlen(curproxy->capture_name);
3737 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 curproxy->to_log |= LW_COOKIE;
3739 }
3740 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3741 struct cap_hdr *hdr;
3742
3743 if (curproxy == &defproxy) {
3744 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 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 }
3748
William Lallemand1a748ae2015-05-19 16:37:23 +02003749 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3750 goto out;
3751
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3753 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3754 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 }
3758
Vincent Bernat02779b62016-04-03 13:48:43 +02003759 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 hdr->next = curproxy->req_cap;
3761 hdr->name = strdup(args[3]);
3762 hdr->namelen = strlen(args[3]);
3763 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003764 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 hdr->index = curproxy->nb_req_cap++;
3766 curproxy->req_cap = hdr;
3767 curproxy->to_log |= LW_REQHDR;
3768 }
3769 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3770 struct cap_hdr *hdr;
3771
3772 if (curproxy == &defproxy) {
3773 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 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
3777
William Lallemand1a748ae2015-05-19 16:37:23 +02003778 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3779 goto out;
3780
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3782 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3783 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003787 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 hdr->next = curproxy->rsp_cap;
3789 hdr->name = strdup(args[3]);
3790 hdr->namelen = strlen(args[3]);
3791 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003792 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 hdr->index = curproxy->nb_rsp_cap++;
3794 curproxy->rsp_cap = hdr;
3795 curproxy->to_log |= LW_RSPHDR;
3796 }
3797 else {
3798 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3799 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 }
3803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003805 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003807
William Lallemanddf1425a2015-04-28 20:17:49 +02003808 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3809 goto out;
3810
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 if (*(args[1]) == 0) {
3812 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3813 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 }
3817 curproxy->conn_retries = atol(args[1]);
3818 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003819 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003820 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003821
3822 if (curproxy == &defproxy) {
3823 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
3826 }
3827
Willy Tarreau20b0de52012-12-24 15:45:22 +01003828 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003829 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003830 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3831 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3832 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3833 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003834 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 +01003835 file, linenum, args[0]);
3836 err_code |= ERR_WARN;
3837 }
3838
Willy Tarreauff011f22011-01-06 17:51:27 +01003839 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003840
Willy Tarreauff011f22011-01-06 17:51:27 +01003841 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003842 err_code |= ERR_ALERT | ERR_ABORT;
3843 goto out;
3844 }
3845
Willy Tarreau5002f572014-04-23 01:32:02 +02003846 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003847 err_code |= warnif_cond_conflicts(rule->cond,
3848 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3849 file, linenum);
3850
Willy Tarreauff011f22011-01-06 17:51:27 +01003851 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003852 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003853 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003854 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003855
3856 if (curproxy == &defproxy) {
3857 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861
3862 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003863 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003864 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3865 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003866 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3867 file, linenum, args[0]);
3868 err_code |= ERR_WARN;
3869 }
3870
3871 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3872
3873 if (!rule) {
3874 err_code |= ERR_ALERT | ERR_ABORT;
3875 goto out;
3876 }
3877
3878 err_code |= warnif_cond_conflicts(rule->cond,
3879 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3880 file, linenum);
3881
3882 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3883 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003884 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3885 /* set the header name and length into the proxy structure */
3886 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3887 err_code |= ERR_WARN;
3888
3889 if (!*args[1]) {
3890 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3891 file, linenum, args[0]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
3896 /* set the desired header name */
3897 free(curproxy->server_id_hdr_name);
3898 curproxy->server_id_hdr_name = strdup(args[1]);
3899 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3900 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003901 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003902 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003903
Willy Tarreaub099aca2008-10-12 17:26:37 +02003904 if (curproxy == &defproxy) {
3905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003908 }
3909
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003910 /* emulate "block" using "http-request block". Since these rules are supposed to
3911 * be processed before all http-request rules, we put them into their own list
3912 * and will insert them at the end.
3913 */
3914 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3915 if (!rule) {
3916 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003917 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003918 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003919 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3920 err_code |= warnif_cond_conflicts(rule->cond,
3921 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3922 file, linenum);
3923 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003924
3925 if (!already_warned(WARN_BLOCK_DEPRECATED))
3926 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]);
3927
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003928 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003929 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003930 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003931
Cyril Bonté99ed3272010-01-24 23:29:44 +01003932 if (curproxy == &defproxy) {
3933 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
3936 }
3937
Willy Tarreaube4653b2015-05-28 15:26:58 +02003938 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003939 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3940 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003943 }
3944
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003945 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003946 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003947 err_code |= warnif_cond_conflicts(rule->cond,
3948 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3949 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003950 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003951 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003952 struct switching_rule *rule;
3953
Willy Tarreaub099aca2008-10-12 17:26:37 +02003954 if (curproxy == &defproxy) {
3955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003958 }
3959
Willy Tarreau55ea7572007-06-17 19:56:27 +02003960 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003961 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003962
3963 if (*(args[1]) == 0) {
3964 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003967 }
3968
Willy Tarreauf51658d2014-04-23 01:21:56 +02003969 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003970 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003971 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3972 file, linenum, errmsg);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003976
Willy Tarreauf51658d2014-04-23 01:21:56 +02003977 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003978 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003979 else if (*args[2]) {
3980 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3981 file, linenum, args[2]);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003985
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003986 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003987 if (!rule) {
3988 Alert("Out of memory error.\n");
3989 goto out;
3990 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003991 rule->cond = cond;
3992 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003993 rule->line = linenum;
3994 rule->file = strdup(file);
3995 if (!rule->file) {
3996 Alert("Out of memory error.\n");
3997 goto out;
3998 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003999 LIST_INIT(&rule->list);
4000 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4001 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004002 else if (strcmp(args[0], "use-server") == 0) {
4003 struct server_rule *rule;
4004
4005 if (curproxy == &defproxy) {
4006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
4010
4011 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4012 err_code |= ERR_WARN;
4013
4014 if (*(args[1]) == 0) {
4015 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
4019
4020 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4021 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4022 file, linenum, args[0]);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025 }
4026
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004027 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004028 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4029 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
4033
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004034 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004035
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004036 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004037 rule->cond = cond;
4038 rule->srv.name = strdup(args[1]);
4039 LIST_INIT(&rule->list);
4040 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4041 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4042 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004043 else if ((!strcmp(args[0], "force-persist")) ||
4044 (!strcmp(args[0], "ignore-persist"))) {
4045 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004046
4047 if (curproxy == &defproxy) {
4048 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4049 err_code |= ERR_ALERT | ERR_FATAL;
4050 goto out;
4051 }
4052
4053 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4054 err_code |= ERR_WARN;
4055
Willy Tarreauef6494c2010-01-28 17:12:36 +01004056 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004057 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4058 file, linenum, args[0]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004063 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004064 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4065 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004070 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4071 * where force-persist is applied.
4072 */
4073 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004074
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004075 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004076 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004077 if (!strcmp(args[0], "force-persist")) {
4078 rule->type = PERSIST_TYPE_FORCE;
4079 } else {
4080 rule->type = PERSIST_TYPE_IGNORE;
4081 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004082 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004083 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004084 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004085 else if (!strcmp(args[0], "stick-table")) {
4086 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004087 struct proxy *other;
4088
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004089 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004090 if (other) {
4091 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4092 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004096
Emeric Brun32da3c42010-09-23 18:39:19 +02004097 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004098 curproxy->table.type = (unsigned int)-1;
4099 while (*args[myidx]) {
4100 const char *err;
4101
4102 if (strcmp(args[myidx], "size") == 0) {
4103 myidx++;
4104 if (!*(args[myidx])) {
4105 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4106 file, linenum, args[myidx-1]);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4111 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4112 file, linenum, *err, args[myidx-1]);
4113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
4115 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004116 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004117 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004118 else if (strcmp(args[myidx], "peers") == 0) {
4119 myidx++;
Godbach50523162013-12-11 19:48:57 +08004120 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004121 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4122 file, linenum, args[myidx-1]);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Godbach50523162013-12-11 19:48:57 +08004125 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004126 curproxy->table.peers.name = strdup(args[myidx++]);
4127 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004128 else if (strcmp(args[myidx], "expire") == 0) {
4129 myidx++;
4130 if (!*(args[myidx])) {
4131 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4132 file, linenum, args[myidx-1]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4137 if (err) {
4138 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4139 file, linenum, *err, args[myidx-1]);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004143 if (val > INT_MAX) {
4144 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4145 file, linenum, val);
4146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
4148 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004149 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004150 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004151 }
4152 else if (strcmp(args[myidx], "nopurge") == 0) {
4153 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004154 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004155 }
4156 else if (strcmp(args[myidx], "type") == 0) {
4157 myidx++;
4158 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4159 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4160 file, linenum, args[myidx]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004164 /* myidx already points to next arg */
4165 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004166 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004167 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004168 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004169
4170 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004171 nw = args[myidx];
4172 while (*nw) {
4173 /* the "store" keyword supports a comma-separated list */
4174 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004175 sa = NULL; /* store arg */
4176 while (*nw && *nw != ',') {
4177 if (*nw == '(') {
4178 *nw = 0;
4179 sa = ++nw;
4180 while (*nw != ')') {
4181 if (!*nw) {
4182 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4183 file, linenum, args[0], cw);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187 nw++;
4188 }
4189 *nw = '\0';
4190 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004191 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004192 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004193 if (*nw)
4194 *nw++ = '\0';
4195 type = stktable_get_data_type(cw);
4196 if (type < 0) {
4197 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4198 file, linenum, args[0], cw);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
Willy Tarreauac782882010-06-20 10:41:54 +02004202
4203 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4204 switch (err) {
4205 case PE_NONE: break;
4206 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004207 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4208 file, linenum, args[0], cw);
4209 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004210 break;
4211
4212 case PE_ARG_MISSING:
4213 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4214 file, linenum, args[0], cw);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217
4218 case PE_ARG_NOT_USED:
4219 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4220 file, linenum, args[0], cw);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223
4224 default:
4225 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4226 file, linenum, args[0], cw);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004229 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004230 }
4231 myidx++;
4232 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004233 else {
4234 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4235 file, linenum, args[myidx]);
4236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004238 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004239 }
4240
4241 if (!curproxy->table.size) {
4242 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4243 file, linenum);
4244 err_code |= ERR_ALERT | ERR_FATAL;
4245 goto out;
4246 }
4247
4248 if (curproxy->table.type == (unsigned int)-1) {
4249 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4250 file, linenum);
4251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
4254 }
4255 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004256 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004257 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004258 int myidx = 0;
4259 const char *name = NULL;
4260 int flags;
4261
4262 if (curproxy == &defproxy) {
4263 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
4266 }
4267
4268 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4269 err_code |= ERR_WARN;
4270 goto out;
4271 }
4272
4273 myidx++;
4274 if ((strcmp(args[myidx], "store") == 0) ||
4275 (strcmp(args[myidx], "store-request") == 0)) {
4276 myidx++;
4277 flags = STK_IS_STORE;
4278 }
4279 else if (strcmp(args[myidx], "store-response") == 0) {
4280 myidx++;
4281 flags = STK_IS_STORE | STK_ON_RSP;
4282 }
4283 else if (strcmp(args[myidx], "match") == 0) {
4284 myidx++;
4285 flags = STK_IS_MATCH;
4286 }
4287 else if (strcmp(args[myidx], "on") == 0) {
4288 myidx++;
4289 flags = STK_IS_MATCH | STK_IS_STORE;
4290 }
4291 else {
4292 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296
4297 if (*(args[myidx]) == 0) {
4298 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004303 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004304 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004305 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004306 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
4309 }
4310
4311 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004312 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4313 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4314 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004315 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004316 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004317 goto out;
4318 }
4319 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004320 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4321 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4322 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004323 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004324 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004325 goto out;
4326 }
4327 }
4328
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004329 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004330 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004331
Emeric Brunb982a3d2010-01-04 15:45:53 +01004332 if (strcmp(args[myidx], "table") == 0) {
4333 myidx++;
4334 name = args[myidx++];
4335 }
4336
Willy Tarreauef6494c2010-01-28 17:12:36 +01004337 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004338 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004339 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4340 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004341 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004342 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004343 goto out;
4344 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004345 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004346 else if (*(args[myidx])) {
4347 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4348 file, linenum, args[0], args[myidx]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004350 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004351 goto out;
4352 }
Emeric Brun97679e72010-09-23 17:56:44 +02004353 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004354 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004355 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004356 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004357
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004358 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004359 rule->cond = cond;
4360 rule->expr = expr;
4361 rule->flags = flags;
4362 rule->table.name = name ? strdup(name) : NULL;
4363 LIST_INIT(&rule->list);
4364 if (flags & STK_ON_RSP)
4365 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4366 else
4367 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004369 else if (!strcmp(args[0], "stats")) {
4370 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4371 curproxy->uri_auth = NULL; /* we must detach from the default config */
4372
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004373 if (!*args[1]) {
4374 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004375 } else if (!strcmp(args[1], "admin")) {
4376 struct stats_admin_rule *rule;
4377
4378 if (curproxy == &defproxy) {
4379 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4380 err_code |= ERR_ALERT | ERR_FATAL;
4381 goto out;
4382 }
4383
4384 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4385 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
4388 }
4389
4390 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4391 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4392 file, linenum, args[0], args[1]);
4393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
4395 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004396 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004397 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4398 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
4401 }
4402
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004403 err_code |= warnif_cond_conflicts(cond,
4404 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4405 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004406
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004407 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004408 rule->cond = cond;
4409 LIST_INIT(&rule->list);
4410 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004411 } else if (!strcmp(args[1], "uri")) {
4412 if (*(args[2]) == 0) {
4413 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4417 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_ABORT;
4419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 }
4421 } else if (!strcmp(args[1], "realm")) {
4422 if (*(args[2]) == 0) {
4423 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4427 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_ABORT;
4429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004430 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004431 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004432 unsigned interval;
4433
4434 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4435 if (err) {
4436 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4437 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004440 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4441 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004442 err_code |= ERR_ALERT | ERR_ABORT;
4443 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004444 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004445 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004446 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004447
4448 if (curproxy == &defproxy) {
4449 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
4452 }
4453
4454 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4455 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4456 err_code |= ERR_ALERT | ERR_ABORT;
4457 goto out;
4458 }
4459
Willy Tarreauff011f22011-01-06 17:51:27 +01004460 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004461 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004462 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4463 file, linenum, args[0]);
4464 err_code |= ERR_WARN;
4465 }
4466
Willy Tarreauff011f22011-01-06 17:51:27 +01004467 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004468
Willy Tarreauff011f22011-01-06 17:51:27 +01004469 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004470 err_code |= ERR_ALERT | ERR_ABORT;
4471 goto out;
4472 }
4473
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004474 err_code |= warnif_cond_conflicts(rule->cond,
4475 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4476 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004477 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004478
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 } else if (!strcmp(args[1], "auth")) {
4480 if (*(args[2]) == 0) {
4481 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4485 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004486 err_code |= ERR_ALERT | ERR_ABORT;
4487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 }
4489 } else if (!strcmp(args[1], "scope")) {
4490 if (*(args[2]) == 0) {
4491 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4495 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_ABORT;
4497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 }
4499 } else if (!strcmp(args[1], "enable")) {
4500 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4501 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004502 err_code |= ERR_ALERT | ERR_ABORT;
4503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004505 } else if (!strcmp(args[1], "hide-version")) {
4506 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4507 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004508 err_code |= ERR_ALERT | ERR_ABORT;
4509 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004510 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004511 } else if (!strcmp(args[1], "show-legends")) {
4512 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4513 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4514 err_code |= ERR_ALERT | ERR_ABORT;
4515 goto out;
4516 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004517 } else if (!strcmp(args[1], "show-node")) {
4518
4519 if (*args[2]) {
4520 int i;
4521 char c;
4522
4523 for (i=0; args[2][i]; i++) {
4524 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004525 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4526 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004527 break;
4528 }
4529
4530 if (!i || args[2][i]) {
4531 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4532 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4533 file, linenum, args[0], args[1]);
4534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
4536 }
4537 }
4538
4539 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4540 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4541 err_code |= ERR_ALERT | ERR_ABORT;
4542 goto out;
4543 }
4544 } else if (!strcmp(args[1], "show-desc")) {
4545 char *desc = NULL;
4546
4547 if (*args[2]) {
4548 int i, len=0;
4549 char *d;
4550
Willy Tarreau348acfe2014-04-14 15:00:39 +02004551 for (i = 2; *args[i]; i++)
4552 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004553
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004554 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004555
Willy Tarreau348acfe2014-04-14 15:00:39 +02004556 d += snprintf(d, desc + len - d, "%s", args[2]);
4557 for (i = 3; *args[i]; i++)
4558 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004559 }
4560
4561 if (!*args[2] && !global.desc)
4562 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4563 file, linenum, args[1]);
4564 else {
4565 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4566 free(desc);
4567 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4568 err_code |= ERR_ALERT | ERR_ABORT;
4569 goto out;
4570 }
4571 free(desc);
4572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004574stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004575 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 +01004576 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 }
4580 }
4581 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004582 int optnum;
4583
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004584 if (*(args[1]) == '\0') {
4585 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4586 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004590
4591 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4592 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004593 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4594 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4595 file, linenum, cfg_opts[optnum].name);
4596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
4598 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004599 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4600 goto out;
4601
Willy Tarreau93893792009-07-23 13:19:11 +02004602 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4603 err_code |= ERR_WARN;
4604 goto out;
4605 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004606
Willy Tarreau3842f002009-06-14 11:39:52 +02004607 curproxy->no_options &= ~cfg_opts[optnum].val;
4608 curproxy->options &= ~cfg_opts[optnum].val;
4609
4610 switch (kwm) {
4611 case KWM_STD:
4612 curproxy->options |= cfg_opts[optnum].val;
4613 break;
4614 case KWM_NO:
4615 curproxy->no_options |= cfg_opts[optnum].val;
4616 break;
4617 case KWM_DEF: /* already cleared */
4618 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004619 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004620
Willy Tarreau93893792009-07-23 13:19:11 +02004621 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004622 }
4623 }
4624
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004625 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4626 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004627 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4628 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4629 file, linenum, cfg_opts2[optnum].name);
4630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
4632 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004633 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4634 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004635 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4636 err_code |= ERR_WARN;
4637 goto out;
4638 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004639
Willy Tarreau3842f002009-06-14 11:39:52 +02004640 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4641 curproxy->options2 &= ~cfg_opts2[optnum].val;
4642
4643 switch (kwm) {
4644 case KWM_STD:
4645 curproxy->options2 |= cfg_opts2[optnum].val;
4646 break;
4647 case KWM_NO:
4648 curproxy->no_options2 |= cfg_opts2[optnum].val;
4649 break;
4650 case KWM_DEF: /* already cleared */
4651 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004652 }
Willy Tarreau93893792009-07-23 13:19:11 +02004653 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004654 }
4655 }
4656
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004657 /* HTTP options override each other. They can be cancelled using
4658 * "no option xxx" which only switches to default mode if the mode
4659 * was this one (useful for cancelling options set in defaults
4660 * sections).
4661 */
4662 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004663 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4664 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004665 if (kwm == KWM_STD) {
4666 curproxy->options &= ~PR_O_HTTP_MODE;
4667 curproxy->options |= PR_O_HTTP_PCL;
4668 goto out;
4669 }
4670 else if (kwm == KWM_NO) {
4671 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4672 curproxy->options &= ~PR_O_HTTP_MODE;
4673 goto out;
4674 }
4675 }
4676 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004677 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4678 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004679 if (kwm == KWM_STD) {
4680 curproxy->options &= ~PR_O_HTTP_MODE;
4681 curproxy->options |= PR_O_HTTP_FCL;
4682 goto out;
4683 }
4684 else if (kwm == KWM_NO) {
4685 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4686 curproxy->options &= ~PR_O_HTTP_MODE;
4687 goto out;
4688 }
4689 }
4690 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004691 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4692 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004693 if (kwm == KWM_STD) {
4694 curproxy->options &= ~PR_O_HTTP_MODE;
4695 curproxy->options |= PR_O_HTTP_SCL;
4696 goto out;
4697 }
4698 else if (kwm == KWM_NO) {
4699 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4700 curproxy->options &= ~PR_O_HTTP_MODE;
4701 goto out;
4702 }
4703 }
4704 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004705 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4706 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004707 if (kwm == KWM_STD) {
4708 curproxy->options &= ~PR_O_HTTP_MODE;
4709 curproxy->options |= PR_O_HTTP_KAL;
4710 goto out;
4711 }
4712 else if (kwm == KWM_NO) {
4713 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4714 curproxy->options &= ~PR_O_HTTP_MODE;
4715 goto out;
4716 }
4717 }
4718 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004719 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4720 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004721 if (kwm == KWM_STD) {
4722 curproxy->options &= ~PR_O_HTTP_MODE;
4723 curproxy->options |= PR_O_HTTP_TUN;
4724 goto out;
4725 }
4726 else if (kwm == KWM_NO) {
4727 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4728 curproxy->options &= ~PR_O_HTTP_MODE;
4729 goto out;
4730 }
4731 }
4732
Joseph Lynch726ab712015-05-11 23:25:34 -07004733 /* Redispatch can take an integer argument that control when the
4734 * resispatch occurs. All values are relative to the retries option.
4735 * This can be cancelled using "no option xxx".
4736 */
4737 if (strcmp(args[1], "redispatch") == 0) {
4738 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4739 err_code |= ERR_WARN;
4740 goto out;
4741 }
4742
4743 curproxy->no_options &= ~PR_O_REDISP;
4744 curproxy->options &= ~PR_O_REDISP;
4745
4746 switch (kwm) {
4747 case KWM_STD:
4748 curproxy->options |= PR_O_REDISP;
4749 curproxy->redispatch_after = -1;
4750 if(*args[2]) {
4751 curproxy->redispatch_after = atol(args[2]);
4752 }
4753 break;
4754 case KWM_NO:
4755 curproxy->no_options |= PR_O_REDISP;
4756 curproxy->redispatch_after = 0;
4757 break;
4758 case KWM_DEF: /* already cleared */
4759 break;
4760 }
4761 goto out;
4762 }
4763
Willy Tarreau3842f002009-06-14 11:39:52 +02004764 if (kwm != KWM_STD) {
4765 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004766 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004767 err_code |= ERR_ALERT | ERR_FATAL;
4768 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004769 }
4770
Emeric Brun3a058f32009-06-30 18:26:00 +02004771 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004772 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004774 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004775 if (*(args[2]) != '\0') {
4776 if (!strcmp(args[2], "clf")) {
4777 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004778 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004779 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004780 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004781 err_code |= ERR_ALERT | ERR_FATAL;
4782 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004783 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004784 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4785 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004786 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004787 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4788 char *oldlogformat = "log-format";
4789 char *clflogformat = "";
4790
4791 if (curproxy->conf.logformat_string == default_http_log_format)
4792 oldlogformat = "option httplog";
4793 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4794 oldlogformat = "option tcplog";
4795 else if (curproxy->conf.logformat_string == clf_http_log_format)
4796 oldlogformat = "option httplog clf";
4797 if (logformat == clf_http_log_format)
4798 clflogformat = " clf";
4799 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4800 file, linenum, clflogformat, oldlogformat);
4801 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004802 if (curproxy->conf.logformat_string != default_http_log_format &&
4803 curproxy->conf.logformat_string != default_tcp_log_format &&
4804 curproxy->conf.logformat_string != clf_http_log_format)
4805 free(curproxy->conf.logformat_string);
4806 curproxy->conf.logformat_string = logformat;
4807
4808 free(curproxy->conf.lfs_file);
4809 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4810 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004811 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004812 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004813 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4814 char *oldlogformat = "log-format";
4815
4816 if (curproxy->conf.logformat_string == default_http_log_format)
4817 oldlogformat = "option httplog";
4818 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4819 oldlogformat = "option tcplog";
4820 else if (curproxy->conf.logformat_string == clf_http_log_format)
4821 oldlogformat = "option httplog clf";
4822 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4823 file, linenum, oldlogformat);
4824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004826 if (curproxy->conf.logformat_string != default_http_log_format &&
4827 curproxy->conf.logformat_string != default_tcp_log_format &&
4828 curproxy->conf.logformat_string != clf_http_log_format)
4829 free(curproxy->conf.logformat_string);
4830 curproxy->conf.logformat_string = default_tcp_log_format;
4831
4832 free(curproxy->conf.lfs_file);
4833 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4834 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004835
4836 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4837 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004840 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004841 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004842 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004843
William Lallemanddf1425a2015-04-28 20:17:49 +02004844 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4845 goto out;
4846
Willy Tarreau13943ab2006-12-31 00:24:10 +01004847 if (curproxy->cap & PR_CAP_FE)
4848 curproxy->options |= PR_O_TCP_CLI_KA;
4849 if (curproxy->cap & PR_CAP_BE)
4850 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 }
4852 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004854 err_code |= ERR_WARN;
4855
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004857 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004858 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004859 curproxy->options2 &= ~PR_O2_CHK_ANY;
4860 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 if (!*args[2]) { /* no argument */
4862 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4863 curproxy->check_len = strlen(DEF_CHECK_REQ);
4864 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004865 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004866 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004868 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004870 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 if (*args[4])
4872 reqlen += strlen(args[4]);
4873 else
4874 reqlen += strlen("HTTP/1.0");
4875
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004876 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004878 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004880 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4881 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004882 }
4883 else if (!strcmp(args[1], "ssl-hello-chk")) {
4884 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004885 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004886 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004887
Willy Tarreaua534fea2008-08-03 12:19:50 +02004888 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004889 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004890 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004891 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004892
4893 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895 }
Willy Tarreau23677902007-05-08 23:50:35 +02004896 else if (!strcmp(args[1], "smtpchk")) {
4897 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004898 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004899 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004900 curproxy->options2 &= ~PR_O2_CHK_ANY;
4901 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004902
4903 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4904 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4905 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4906 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4907 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4908 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004909 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004910 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4911 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4912 } else {
4913 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4914 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4915 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4916 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4917 }
4918 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004919 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4920 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004921 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004922 else if (!strcmp(args[1], "pgsql-check")) {
4923 /* use PostgreSQL request to check servers' health */
4924 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4925 err_code |= ERR_WARN;
4926
4927 free(curproxy->check_req);
4928 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004929 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004930 curproxy->options2 |= PR_O2_PGSQL_CHK;
4931
4932 if (*(args[2])) {
4933 int cur_arg = 2;
4934
4935 while (*(args[cur_arg])) {
4936 if (strcmp(args[cur_arg], "user") == 0) {
4937 char * packet;
4938 uint32_t packet_len;
4939 uint32_t pv;
4940
4941 /* suboption header - needs additional argument for it */
4942 if (*(args[cur_arg+1]) == 0) {
4943 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4944 file, linenum, args[0], args[1], args[cur_arg]);
4945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
4947 }
4948
4949 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4950 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4951 pv = htonl(0x30000); /* protocol version 3.0 */
4952
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004953 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004954
4955 memcpy(packet + 4, &pv, 4);
4956
4957 /* copy "user" */
4958 memcpy(packet + 8, "user", 4);
4959
4960 /* copy username */
4961 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4962
4963 free(curproxy->check_req);
4964 curproxy->check_req = packet;
4965 curproxy->check_len = packet_len;
4966
4967 packet_len = htonl(packet_len);
4968 memcpy(packet, &packet_len, 4);
4969 cur_arg += 2;
4970 } else {
4971 /* unknown suboption - catchall */
4972 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4973 file, linenum, args[0], args[1]);
4974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
4976 }
4977 } /* end while loop */
4978 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004979 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4980 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004981 }
4982
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004983 else if (!strcmp(args[1], "redis-check")) {
4984 /* use REDIS PING request to check servers' health */
4985 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4986 err_code |= ERR_WARN;
4987
4988 free(curproxy->check_req);
4989 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004990 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004991 curproxy->options2 |= PR_O2_REDIS_CHK;
4992
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004993 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004994 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4995 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004996
4997 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4998 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004999 }
5000
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005001 else if (!strcmp(args[1], "mysql-check")) {
5002 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005003 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5004 err_code |= ERR_WARN;
5005
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005006 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01005007 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005008 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005009 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005010
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005011 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005012 * const char mysql40_client_auth_pkt[] = {
5013 * "\x0e\x00\x00" // packet length
5014 * "\x01" // packet number
5015 * "\x00\x00" // client capabilities
5016 * "\x00\x00\x01" // max packet
5017 * "haproxy\x00" // username (null terminated string)
5018 * "\x00" // filler (always 0x00)
5019 * "\x01\x00\x00" // packet length
5020 * "\x00" // packet number
5021 * "\x01" // COM_QUIT command
5022 * };
5023 */
5024
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005025 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5026 * const char mysql41_client_auth_pkt[] = {
5027 * "\x0e\x00\x00\" // packet length
5028 * "\x01" // packet number
5029 * "\x00\x00\x00\x00" // client capabilities
5030 * "\x00\x00\x00\x01" // max packet
5031 * "\x21" // character set (UTF-8)
5032 * char[23] // All zeroes
5033 * "haproxy\x00" // username (null terminated string)
5034 * "\x00" // filler (always 0x00)
5035 * "\x01\x00\x00" // packet length
5036 * "\x00" // packet number
5037 * "\x01" // COM_QUIT command
5038 * };
5039 */
5040
5041
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005042 if (*(args[2])) {
5043 int cur_arg = 2;
5044
5045 while (*(args[cur_arg])) {
5046 if (strcmp(args[cur_arg], "user") == 0) {
5047 char *mysqluser;
5048 int packetlen, reqlen, userlen;
5049
5050 /* suboption header - needs additional argument for it */
5051 if (*(args[cur_arg+1]) == 0) {
5052 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5053 file, linenum, args[0], args[1], args[cur_arg]);
5054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
5056 }
5057 mysqluser = args[cur_arg + 1];
5058 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005059
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005060 if (*(args[cur_arg+2])) {
5061 if (!strcmp(args[cur_arg+2], "post-41")) {
5062 packetlen = userlen + 7 + 27;
5063 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005064
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005065 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005066 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005067 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005068
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005069 snprintf(curproxy->check_req, 4, "%c%c%c",
5070 ((unsigned char) packetlen & 0xff),
5071 ((unsigned char) (packetlen >> 8) & 0xff),
5072 ((unsigned char) (packetlen >> 16) & 0xff));
5073
5074 curproxy->check_req[3] = 1;
5075 curproxy->check_req[5] = 130;
5076 curproxy->check_req[11] = 1;
5077 curproxy->check_req[12] = 33;
5078 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5079 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5080 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5081 cur_arg += 3;
5082 } else {
5083 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
5086 }
5087 } else {
5088 packetlen = userlen + 7;
5089 reqlen = packetlen + 9;
5090
5091 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005092 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005093 curproxy->check_len = reqlen;
5094
5095 snprintf(curproxy->check_req, 4, "%c%c%c",
5096 ((unsigned char) packetlen & 0xff),
5097 ((unsigned char) (packetlen >> 8) & 0xff),
5098 ((unsigned char) (packetlen >> 16) & 0xff));
5099
5100 curproxy->check_req[3] = 1;
5101 curproxy->check_req[5] = 128;
5102 curproxy->check_req[8] = 1;
5103 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5104 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5105 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5106 cur_arg += 2;
5107 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005108 } else {
5109 /* unknown suboption - catchall */
5110 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5111 file, linenum, args[0], args[1]);
5112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
5114 }
5115 } /* end while loop */
5116 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005117 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005118 else if (!strcmp(args[1], "ldap-check")) {
5119 /* use LDAP request to check servers' health */
5120 free(curproxy->check_req);
5121 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005122 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005123 curproxy->options2 |= PR_O2_LDAP_CHK;
5124
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005125 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005126 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5127 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005128 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5129 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005130 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005131 else if (!strcmp(args[1], "spop-check")) {
5132 if (curproxy == &defproxy) {
5133 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5134 file, linenum, args[0], args[1]);
5135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
5137 }
5138 if (curproxy->cap & PR_CAP_FE) {
5139 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5140 file, linenum, args[0], args[1]);
5141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
5143 }
5144
5145 /* use SPOE request to check servers' health */
5146 free(curproxy->check_req);
5147 curproxy->check_req = NULL;
5148 curproxy->options2 &= ~PR_O2_CHK_ANY;
5149 curproxy->options2 |= PR_O2_SPOP_CHK;
5150
Christopher Faulet8ef75252017-02-20 22:56:03 +01005151 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005152 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
5155 }
5156 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5157 goto out;
5158 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005159 else if (!strcmp(args[1], "tcp-check")) {
5160 /* use raw TCPCHK send/expect to check servers' health */
5161 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5162 err_code |= ERR_WARN;
5163
5164 free(curproxy->check_req);
5165 curproxy->check_req = NULL;
5166 curproxy->options2 &= ~PR_O2_CHK_ANY;
5167 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005168 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5169 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005170 }
Simon Horman98637e52014-06-20 12:30:16 +09005171 else if (!strcmp(args[1], "external-check")) {
5172 /* excute an external command to check servers' health */
5173 free(curproxy->check_req);
5174 curproxy->check_req = NULL;
5175 curproxy->options2 &= ~PR_O2_CHK_ANY;
5176 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005177 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5178 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005179 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005180 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005181 int cur_arg;
5182
5183 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5184 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005185 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005186
Willy Tarreau87cf5142011-08-19 22:57:24 +02005187 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005188
5189 free(curproxy->fwdfor_hdr_name);
5190 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5191 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5192
5193 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5194 cur_arg = 2;
5195 while (*(args[cur_arg])) {
5196 if (!strcmp(args[cur_arg], "except")) {
5197 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005198 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005199 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5200 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005203 }
5204 /* flush useless bits */
5205 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005206 cur_arg += 2;
5207 } else if (!strcmp(args[cur_arg], "header")) {
5208 /* suboption header - needs additional argument for it */
5209 if (*(args[cur_arg+1]) == 0) {
5210 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5211 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005214 }
5215 free(curproxy->fwdfor_hdr_name);
5216 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5217 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5218 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005219 } else if (!strcmp(args[cur_arg], "if-none")) {
5220 curproxy->options &= ~PR_O_FF_ALWAYS;
5221 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005222 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005223 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005224 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005225 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005228 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005229 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005230 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005231 else if (!strcmp(args[1], "originalto")) {
5232 int cur_arg;
5233
5234 /* insert x-original-to field, but not for the IP address listed as an except.
5235 * set default options (ie: bitfield, header name, etc)
5236 */
5237
5238 curproxy->options |= PR_O_ORGTO;
5239
5240 free(curproxy->orgto_hdr_name);
5241 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5242 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5243
Willy Tarreau87cf5142011-08-19 22:57:24 +02005244 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005245 cur_arg = 2;
5246 while (*(args[cur_arg])) {
5247 if (!strcmp(args[cur_arg], "except")) {
5248 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005249 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 +02005250 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5251 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005252 err_code |= ERR_ALERT | ERR_FATAL;
5253 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005254 }
5255 /* flush useless bits */
5256 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5257 cur_arg += 2;
5258 } else if (!strcmp(args[cur_arg], "header")) {
5259 /* suboption header - needs additional argument for it */
5260 if (*(args[cur_arg+1]) == 0) {
5261 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5262 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005265 }
5266 free(curproxy->orgto_hdr_name);
5267 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5268 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5269 cur_arg += 2;
5270 } else {
5271 /* unknown suboption - catchall */
5272 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5273 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005274 err_code |= ERR_ALERT | ERR_FATAL;
5275 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005276 }
5277 } /* end while loop */
5278 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 else {
5280 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 }
Willy Tarreau93893792009-07-23 13:19:11 +02005284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005286 else if (!strcmp(args[0], "default_backend")) {
5287 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005288 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005289
5290 if (*(args[1]) == 0) {
5291 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005294 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005295 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005296 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005297
5298 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5299 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005302 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005304
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005305 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5306 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 +01005307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005308 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 /* enable reconnections to dispatch */
5310 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005311
5312 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005315 else if (!strcmp(args[0], "http-reuse")) {
5316 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5317 err_code |= ERR_WARN;
5318
5319 if (strcmp(args[1], "never") == 0) {
5320 /* enable a graceful server shutdown on an HTTP 404 response */
5321 curproxy->options &= ~PR_O_REUSE_MASK;
5322 curproxy->options |= PR_O_REUSE_NEVR;
5323 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5324 goto out;
5325 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005326 else if (strcmp(args[1], "safe") == 0) {
5327 /* enable a graceful server shutdown on an HTTP 404 response */
5328 curproxy->options &= ~PR_O_REUSE_MASK;
5329 curproxy->options |= PR_O_REUSE_SAFE;
5330 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5331 goto out;
5332 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005333 else if (strcmp(args[1], "aggressive") == 0) {
5334 curproxy->options &= ~PR_O_REUSE_MASK;
5335 curproxy->options |= PR_O_REUSE_AGGR;
5336 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5337 goto out;
5338 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005339 else if (strcmp(args[1], "always") == 0) {
5340 /* enable a graceful server shutdown on an HTTP 404 response */
5341 curproxy->options &= ~PR_O_REUSE_MASK;
5342 curproxy->options |= PR_O_REUSE_ALWS;
5343 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5344 goto out;
5345 }
5346 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005347 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005352 else if (!strcmp(args[0], "http-check")) {
5353 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005355
5356 if (strcmp(args[1], "disable-on-404") == 0) {
5357 /* enable a graceful server shutdown on an HTTP 404 response */
5358 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005359 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5360 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005361 }
Willy Tarreauef781042010-01-27 11:53:01 +01005362 else if (strcmp(args[1], "send-state") == 0) {
5363 /* enable emission of the apparent state of a server in HTTP checks */
5364 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005365 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5366 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005367 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005368 else if (strcmp(args[1], "expect") == 0) {
5369 const char *ptr_arg;
5370 int cur_arg;
5371
5372 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5373 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
5377
5378 cur_arg = 2;
5379 /* consider exclamation marks, sole or at the beginning of a word */
5380 while (*(ptr_arg = args[cur_arg])) {
5381 while (*ptr_arg == '!') {
5382 curproxy->options2 ^= PR_O2_EXP_INV;
5383 ptr_arg++;
5384 }
5385 if (*ptr_arg)
5386 break;
5387 cur_arg++;
5388 }
5389 /* now ptr_arg points to the beginning of a word past any possible
5390 * exclamation mark, and cur_arg is the argument which holds this word.
5391 */
5392 if (strcmp(ptr_arg, "status") == 0) {
5393 if (!*(args[cur_arg + 1])) {
5394 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5395 file, linenum, args[0], args[1], ptr_arg);
5396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
5399 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005400 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005401 curproxy->expect_str = strdup(args[cur_arg + 1]);
5402 }
5403 else if (strcmp(ptr_arg, "string") == 0) {
5404 if (!*(args[cur_arg + 1])) {
5405 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5406 file, linenum, args[0], args[1], ptr_arg);
5407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
5409 }
5410 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005411 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005412 curproxy->expect_str = strdup(args[cur_arg + 1]);
5413 }
5414 else if (strcmp(ptr_arg, "rstatus") == 0) {
5415 if (!*(args[cur_arg + 1])) {
5416 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5417 file, linenum, args[0], args[1], ptr_arg);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005422 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005423 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005424 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005425 free(curproxy->expect_regex);
5426 curproxy->expect_regex = NULL;
5427 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005428 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005429 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5430 error = NULL;
5431 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5432 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5433 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5434 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
5437 }
5438 }
5439 else if (strcmp(ptr_arg, "rstring") == 0) {
5440 if (!*(args[cur_arg + 1])) {
5441 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5442 file, linenum, args[0], args[1], ptr_arg);
5443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
5446 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005447 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005448 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005449 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005450 free(curproxy->expect_regex);
5451 curproxy->expect_regex = NULL;
5452 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005453 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005454 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5455 error = NULL;
5456 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5457 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5458 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5459 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
5462 }
5463 }
5464 else {
5465 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5466 file, linenum, args[0], args[1], ptr_arg);
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
5470 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005471 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005472 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 +02005473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005475 }
5476 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005477 else if (!strcmp(args[0], "tcp-check")) {
5478 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5479 err_code |= ERR_WARN;
5480
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005481 if (strcmp(args[1], "comment") == 0) {
5482 int cur_arg;
5483 struct tcpcheck_rule *tcpcheck;
5484
5485 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005486 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005487 tcpcheck->action = TCPCHK_ACT_COMMENT;
5488
5489 if (!*args[cur_arg + 1]) {
5490 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5491 file, linenum, args[cur_arg]);
5492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
5494 }
5495
5496 tcpcheck->comment = strdup(args[cur_arg + 1]);
5497
5498 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005499 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5500 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005501 }
5502 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005503 const char *ptr_arg;
5504 int cur_arg;
5505 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005506
5507 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005508 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5509 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5510 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5511 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5512 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005513
Willy Tarreau5581c272015-05-13 12:24:53 +02005514 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5515 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5516 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5517 file, linenum);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005520 }
5521
5522 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005523 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005524 tcpcheck->action = TCPCHK_ACT_CONNECT;
5525
5526 /* parsing each parameters to fill up the rule */
5527 while (*(ptr_arg = args[cur_arg])) {
5528 /* tcp port */
5529 if (strcmp(args[cur_arg], "port") == 0) {
5530 if ( (atol(args[cur_arg + 1]) > 65535) ||
5531 (atol(args[cur_arg + 1]) < 1) ){
5532 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5533 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536 }
5537 tcpcheck->port = atol(args[cur_arg + 1]);
5538 cur_arg += 2;
5539 }
5540 /* send proxy protocol */
5541 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5542 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5543 cur_arg++;
5544 }
5545#ifdef USE_OPENSSL
5546 else if (strcmp(args[cur_arg], "ssl") == 0) {
5547 curproxy->options |= PR_O_TCPCHK_SSL;
5548 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5549 cur_arg++;
5550 }
5551#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005552 /* comment for this tcpcheck line */
5553 else if (strcmp(args[cur_arg], "comment") == 0) {
5554 if (!*args[cur_arg + 1]) {
5555 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5556 file, linenum, args[cur_arg]);
5557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
5559 }
5560 tcpcheck->comment = strdup(args[cur_arg + 1]);
5561 cur_arg += 2;
5562 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005563 else {
5564#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005565 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 +01005566#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005567 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 +01005568#endif /* USE_OPENSSL */
5569 file, linenum, args[0], args[1], args[cur_arg]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573
5574 }
5575
5576 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5577 }
5578 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005579 if (! *(args[2]) ) {
5580 /* SEND string expected */
5581 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5582 file, linenum, args[0], args[1], args[2]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 } else {
5586 struct tcpcheck_rule *tcpcheck;
5587
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005588 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005589
5590 tcpcheck->action = TCPCHK_ACT_SEND;
5591 tcpcheck->string_len = strlen(args[2]);
5592 tcpcheck->string = strdup(args[2]);
5593 tcpcheck->expect_regex = NULL;
5594
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005595 /* comment for this tcpcheck line */
5596 if (strcmp(args[3], "comment") == 0) {
5597 if (!*args[4]) {
5598 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5599 file, linenum, args[3]);
5600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
5602 }
5603 tcpcheck->comment = strdup(args[4]);
5604 }
5605
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005606 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5607 }
5608 }
5609 else if (strcmp(args[1], "send-binary") == 0) {
5610 if (! *(args[2]) ) {
5611 /* SEND binary string expected */
5612 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5613 file, linenum, args[0], args[1], args[2]);
5614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
5616 } else {
5617 struct tcpcheck_rule *tcpcheck;
5618 char *err = NULL;
5619
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005620 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005621
5622 tcpcheck->action = TCPCHK_ACT_SEND;
5623 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5624 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5625 file, linenum, args[0], args[1], args[2], err);
5626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
5629 tcpcheck->expect_regex = NULL;
5630
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005631 /* comment for this tcpcheck line */
5632 if (strcmp(args[3], "comment") == 0) {
5633 if (!*args[4]) {
5634 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5635 file, linenum, args[3]);
5636 err_code |= ERR_ALERT | ERR_FATAL;
5637 goto out;
5638 }
5639 tcpcheck->comment = strdup(args[4]);
5640 }
5641
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005642 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5643 }
5644 }
5645 else if (strcmp(args[1], "expect") == 0) {
5646 const char *ptr_arg;
5647 int cur_arg;
5648 int inverse = 0;
5649
5650 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5651 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5652 err_code |= ERR_ALERT | ERR_FATAL;
5653 goto out;
5654 }
5655
5656 cur_arg = 2;
5657 /* consider exclamation marks, sole or at the beginning of a word */
5658 while (*(ptr_arg = args[cur_arg])) {
5659 while (*ptr_arg == '!') {
5660 inverse = !inverse;
5661 ptr_arg++;
5662 }
5663 if (*ptr_arg)
5664 break;
5665 cur_arg++;
5666 }
5667 /* now ptr_arg points to the beginning of a word past any possible
5668 * exclamation mark, and cur_arg is the argument which holds this word.
5669 */
5670 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005671 struct tcpcheck_rule *tcpcheck;
5672 char *err = NULL;
5673
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005674 if (!*(args[cur_arg + 1])) {
5675 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5676 file, linenum, args[0], args[1], ptr_arg);
5677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
5679 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005680
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005681 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005682
5683 tcpcheck->action = TCPCHK_ACT_EXPECT;
5684 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5685 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5686 file, linenum, args[0], args[1], args[2], err);
5687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
5689 }
5690 tcpcheck->expect_regex = NULL;
5691 tcpcheck->inverse = inverse;
5692
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005693 /* tcpcheck comment */
5694 cur_arg += 2;
5695 if (strcmp(args[cur_arg], "comment") == 0) {
5696 if (!*args[cur_arg + 1]) {
5697 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5698 file, linenum, args[cur_arg + 1]);
5699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701 }
5702 tcpcheck->comment = strdup(args[cur_arg + 1]);
5703 }
5704
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005705 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5706 }
5707 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005708 struct tcpcheck_rule *tcpcheck;
5709
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005710 if (!*(args[cur_arg + 1])) {
5711 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5712 file, linenum, args[0], args[1], ptr_arg);
5713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
5715 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005716
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005717 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005718
5719 tcpcheck->action = TCPCHK_ACT_EXPECT;
5720 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5721 tcpcheck->string = strdup(args[cur_arg + 1]);
5722 tcpcheck->expect_regex = NULL;
5723 tcpcheck->inverse = inverse;
5724
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005725 /* tcpcheck comment */
5726 cur_arg += 2;
5727 if (strcmp(args[cur_arg], "comment") == 0) {
5728 if (!*args[cur_arg + 1]) {
5729 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5730 file, linenum, args[cur_arg + 1]);
5731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
5733 }
5734 tcpcheck->comment = strdup(args[cur_arg + 1]);
5735 }
5736
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005737 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5738 }
5739 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005740 struct tcpcheck_rule *tcpcheck;
5741
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005742 if (!*(args[cur_arg + 1])) {
5743 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5744 file, linenum, args[0], args[1], ptr_arg);
5745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
5747 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005748
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005749 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005750
5751 tcpcheck->action = TCPCHK_ACT_EXPECT;
5752 tcpcheck->string_len = 0;
5753 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005754 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5755 error = NULL;
5756 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5757 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5758 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5759 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
5762 }
5763 tcpcheck->inverse = inverse;
5764
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005765 /* tcpcheck comment */
5766 cur_arg += 2;
5767 if (strcmp(args[cur_arg], "comment") == 0) {
5768 if (!*args[cur_arg + 1]) {
5769 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5770 file, linenum, args[cur_arg + 1]);
5771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
5773 }
5774 tcpcheck->comment = strdup(args[cur_arg + 1]);
5775 }
5776
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005777 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5778 }
5779 else {
5780 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5781 file, linenum, args[0], args[1], ptr_arg);
5782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
5784 }
5785 }
5786 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005787 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005788 err_code |= ERR_ALERT | ERR_FATAL;
5789 goto out;
5790 }
5791 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005792 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005793 if (curproxy == &defproxy) {
5794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005797 }
5798
Willy Tarreaub80c2302007-11-30 20:51:32 +01005799 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005800 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005801
5802 if (strcmp(args[1], "fail") == 0) {
5803 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005804 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005805 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5806 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005807 err_code |= ERR_ALERT | ERR_FATAL;
5808 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005809 }
5810
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005811 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005812 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5813 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_ALERT | ERR_FATAL;
5815 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005816 }
5817 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5818 }
5819 else {
5820 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005821 err_code |= ERR_ALERT | ERR_FATAL;
5822 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005823 }
5824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825#ifdef TPROXY
5826 else if (!strcmp(args[0], "transparent")) {
5827 /* enable transparent proxy connections */
5828 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005829 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 }
5832#endif
5833 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005834 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005836
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 if (*(args[1]) == 0) {
5838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 }
5842 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005843 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005846 else if (!strcmp(args[0], "backlog")) { /* backlog */
5847 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005848 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005849
5850 if (*(args[1]) == 0) {
5851 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005852 err_code |= ERR_ALERT | ERR_FATAL;
5853 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005854 }
5855 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005856 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5857 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005858 }
Willy Tarreau86034312006-12-29 00:10:33 +01005859 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005862
Willy Tarreau86034312006-12-29 00:10:33 +01005863 if (*(args[1]) == 0) {
5864 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005867 }
5868 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005869 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5870 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5873 if (*(args[1]) == 0) {
5874 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005878 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5879 if (err) {
5880 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5881 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005884 }
5885 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005886 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 }
5889 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005890 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005891 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005892 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005893
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 if (curproxy == &defproxy) {
5895 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005899 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005901
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005902 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005903 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005904 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005905 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005906 goto out;
5907 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005908
5909 proto = protocol_by_family(sk->ss_family);
5910 if (!proto || !proto->connect) {
5911 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5912 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005913 err_code |= ERR_ALERT | ERR_FATAL;
5914 goto out;
5915 }
5916
5917 if (port1 != port2) {
5918 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5919 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005920 err_code |= ERR_ALERT | ERR_FATAL;
5921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005923
5924 if (!port1) {
5925 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5926 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005927 err_code |= ERR_ALERT | ERR_FATAL;
5928 goto out;
5929 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005930
William Lallemanddf1425a2015-04-28 20:17:49 +02005931 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5932 goto out;
5933
Willy Tarreaud5191e72010-02-09 20:50:45 +01005934 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005935 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 }
5937 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005938 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005939 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005940
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005941 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5942 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005943 err_code |= ERR_ALERT | ERR_FATAL;
5944 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005946 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005947 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005948 /**
5949 * The syntax for hash-type config element is
5950 * hash-type {map-based|consistent} [[<algo>] avalanche]
5951 *
5952 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5953 */
5954 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005955
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005956 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5957 err_code |= ERR_WARN;
5958
5959 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005960 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5961 }
5962 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005963 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5964 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005965 else if (strcmp(args[1], "avalanche") == 0) {
5966 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]);
5967 err_code |= ERR_ALERT | ERR_FATAL;
5968 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005969 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005970 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005971 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
Bhaskar98634f02013-10-29 23:30:51 -04005975
5976 /* set the hash function to use */
5977 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005978 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005979 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005980
5981 /* if consistent with no argument, then avalanche modifier is also applied */
5982 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5983 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005984 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005985 /* set the hash function */
5986 if (!strcmp(args[2], "sdbm")) {
5987 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5988 }
5989 else if (!strcmp(args[2], "djb2")) {
5990 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005991 }
5992 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005993 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005994 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005995 else if (!strcmp(args[2], "crc32")) {
5996 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5997 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005998 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005999 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 -05006000 err_code |= ERR_ALERT | ERR_FATAL;
6001 goto out;
6002 }
6003
6004 /* set the hash modifier */
6005 if (!strcmp(args[3], "avalanche")) {
6006 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
6007 }
6008 else if (*args[3]) {
6009 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
6010 err_code |= ERR_ALERT | ERR_FATAL;
6011 goto out;
6012 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01006013 }
William Lallemanda73203e2012-03-12 12:48:57 +01006014 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04006015 else if (strcmp(args[0], "hash-balance-factor") == 0) {
6016 if (*(args[1]) == 0) {
6017 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
6018 err_code |= ERR_ALERT | ERR_FATAL;
6019 goto out;
6020 }
6021 curproxy->lbprm.chash.balance_factor = atol(args[1]);
6022 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
6023 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
6024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
6026 }
6027 }
William Lallemanda73203e2012-03-12 12:48:57 +01006028 else if (strcmp(args[0], "unique-id-format") == 0) {
6029 if (!*(args[1])) {
6030 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6031 err_code |= ERR_ALERT | ERR_FATAL;
6032 goto out;
6033 }
William Lallemand3203ff42012-11-11 17:30:56 +01006034 if (*(args[2])) {
6035 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6036 err_code |= ERR_ALERT | ERR_FATAL;
6037 goto out;
6038 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006039 free(curproxy->conf.uniqueid_format_string);
6040 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006041
Willy Tarreau62a61232013-04-12 18:13:46 +02006042 free(curproxy->conf.uif_file);
6043 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6044 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006045 }
William Lallemanda73203e2012-03-12 12:48:57 +01006046
6047 else if (strcmp(args[0], "unique-id-header") == 0) {
6048 if (!*(args[1])) {
6049 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6050 err_code |= ERR_ALERT | ERR_FATAL;
6051 goto out;
6052 }
6053 free(curproxy->header_unique_id);
6054 curproxy->header_unique_id = strdup(args[1]);
6055 }
6056
William Lallemand723b73a2012-02-08 16:37:49 +01006057 else if (strcmp(args[0], "log-format") == 0) {
6058 if (!*(args[1])) {
6059 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6060 err_code |= ERR_ALERT | ERR_FATAL;
6061 goto out;
6062 }
William Lallemand3203ff42012-11-11 17:30:56 +01006063 if (*(args[2])) {
6064 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
6067 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006068 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
6069 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02006070
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006071 if (curproxy->conf.logformat_string == default_http_log_format)
6072 oldlogformat = "option httplog";
6073 else if (curproxy->conf.logformat_string == default_tcp_log_format)
6074 oldlogformat = "option tcplog";
6075 else if (curproxy->conf.logformat_string == clf_http_log_format)
6076 oldlogformat = "option httplog clf";
6077 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
6078 file, linenum, oldlogformat);
6079 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006080 if (curproxy->conf.logformat_string != default_http_log_format &&
6081 curproxy->conf.logformat_string != default_tcp_log_format &&
6082 curproxy->conf.logformat_string != clf_http_log_format)
6083 free(curproxy->conf.logformat_string);
6084 curproxy->conf.logformat_string = strdup(args[1]);
6085
6086 free(curproxy->conf.lfs_file);
6087 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6088 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006089
6090 /* get a chance to improve log-format error reporting by
6091 * reporting the correct line-number when possible.
6092 */
6093 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6094 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6095 file, linenum, curproxy->id);
6096 err_code |= ERR_WARN;
6097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006099 else if (!strcmp(args[0], "log-format-sd")) {
6100 if (!*(args[1])) {
6101 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
6104 }
6105 if (*(args[2])) {
6106 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6107 err_code |= ERR_ALERT | ERR_FATAL;
6108 goto out;
6109 }
6110
6111 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6112 free(curproxy->conf.logformat_sd_string);
6113 curproxy->conf.logformat_sd_string = strdup(args[1]);
6114
6115 free(curproxy->conf.lfsd_file);
6116 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6117 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6118
6119 /* get a chance to improve log-format-sd error reporting by
6120 * reporting the correct line-number when possible.
6121 */
6122 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6123 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6124 file, linenum, curproxy->id);
6125 err_code |= ERR_WARN;
6126 }
6127 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006128 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6129 if (*(args[1]) == 0) {
6130 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
6133 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006134 chunk_destroy(&curproxy->log_tag);
6135 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006136 }
William Lallemand0f99e342011-10-12 17:50:54 +02006137 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6138 /* delete previous herited or defined syslog servers */
6139 struct logsrv *back;
6140
6141 if (*(args[1]) != 0) {
6142 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6143 err_code |= ERR_ALERT | ERR_FATAL;
6144 goto out;
6145 }
6146
William Lallemand723b73a2012-02-08 16:37:49 +01006147 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6148 LIST_DEL(&tmplogsrv->list);
6149 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006150 }
6151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006153 struct logsrv *logsrv;
6154
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006156 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006157 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006158 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006159 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006160 LIST_INIT(&node->list);
6161 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006163 }
6164 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006165 struct sockaddr_storage *sk;
6166 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006167 int arg = 0;
6168 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006169
Vincent Bernat02779b62016-04-03 13:48:43 +02006170 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171
Willy Tarreau18324f52014-06-27 18:10:07 +02006172 /* just after the address, a length may be specified */
6173 if (strcmp(args[arg+2], "len") == 0) {
6174 len = atoi(args[arg+3]);
6175 if (len < 80 || len > 65535) {
6176 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6177 file, linenum, args[arg+3]);
6178 err_code |= ERR_ALERT | ERR_FATAL;
6179 goto out;
6180 }
6181 logsrv->maxlen = len;
6182
6183 /* skip these two args */
6184 arg += 2;
6185 }
6186 else
6187 logsrv->maxlen = MAX_SYSLOG_LEN;
6188
Christopher Faulet084aa962017-08-29 16:54:41 +02006189 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006190 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006191
Dragan Dosen1322d092015-09-22 16:05:32 +02006192 /* after the length, a format may be specified */
6193 if (strcmp(args[arg+2], "format") == 0) {
6194 logsrv->format = get_log_format(args[arg+3]);
6195 if (logsrv->format < 0) {
6196 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6197 err_code |= ERR_ALERT | ERR_FATAL;
6198 goto out;
6199 }
6200
6201 /* skip these two args */
6202 arg += 2;
6203 }
6204
William Lallemanddf1425a2015-04-28 20:17:49 +02006205 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6206 goto out;
6207
Willy Tarreau18324f52014-06-27 18:10:07 +02006208 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006209 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006210 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006211 err_code |= ERR_ALERT | ERR_FATAL;
6212 goto out;
6213
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 }
6215
William Lallemand0f99e342011-10-12 17:50:54 +02006216 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006217 if (*(args[arg+3])) {
6218 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006219 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006220 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006221 err_code |= ERR_ALERT | ERR_FATAL;
6222 goto out;
6223
Willy Tarreaubaaee002006-06-26 02:48:02 +02006224 }
6225 }
6226
William Lallemand0f99e342011-10-12 17:50:54 +02006227 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006228 if (*(args[arg+4])) {
6229 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006230 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006231 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006235 }
6236 }
6237
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006238 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006239 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006240 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006241 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006242 goto out;
6243 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006244
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006245 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006246
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006247 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006248 if (port1 != port2) {
6249 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6250 file, linenum, args[0], args[1]);
6251 err_code |= ERR_ALERT | ERR_FATAL;
6252 goto out;
6253 }
6254
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006255 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006256 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006257 }
William Lallemand0f99e342011-10-12 17:50:54 +02006258
6259 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
6261 else {
6262 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6263 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 }
6267 }
6268 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006269 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006270 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006271 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006272 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006273
Willy Tarreau977b8e42006-12-29 14:19:17 +01006274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006275 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006276
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006278 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6279 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006280 err_code |= ERR_ALERT | ERR_FATAL;
6281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006283
6284 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006285 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6286 free(curproxy->conn_src.iface_name);
6287 curproxy->conn_src.iface_name = NULL;
6288 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006289
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006290 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006291 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006292 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006293 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006294 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006295 goto out;
6296 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006297
6298 proto = protocol_by_family(sk->ss_family);
6299 if (!proto || !proto->connect) {
6300 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006301 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006302 err_code |= ERR_ALERT | ERR_FATAL;
6303 goto out;
6304 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006305
6306 if (port1 != port2) {
6307 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6308 file, linenum, args[0], args[1]);
6309 err_code |= ERR_ALERT | ERR_FATAL;
6310 goto out;
6311 }
6312
Willy Tarreauef9a3602012-12-08 22:29:20 +01006313 curproxy->conn_src.source_addr = *sk;
6314 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006315
6316 cur_arg = 2;
6317 while (*(args[cur_arg])) {
6318 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006319#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006320 if (!*args[cur_arg + 1]) {
6321 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6322 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006323 err_code |= ERR_ALERT | ERR_FATAL;
6324 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006325 }
6326
6327 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006328 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6329 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006330 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006331 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6332 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006333 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6334 char *name, *end;
6335
6336 name = args[cur_arg+1] + 7;
6337 while (isspace(*name))
6338 name++;
6339
6340 end = name;
6341 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6342 end++;
6343
Willy Tarreauef9a3602012-12-08 22:29:20 +01006344 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6345 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6346 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6347 curproxy->conn_src.bind_hdr_len = end - name;
6348 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6349 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6350 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006351
6352 /* now look for an occurrence number */
6353 while (isspace(*end))
6354 end++;
6355 if (*end == ',') {
6356 end++;
6357 name = end;
6358 if (*end == '-')
6359 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006360 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006361 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006362 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006363 }
6364
Willy Tarreauef9a3602012-12-08 22:29:20 +01006365 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006366 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6367 " occurrences values smaller than %d.\n",
6368 file, linenum, MAX_HDR_HISTORY);
6369 err_code |= ERR_ALERT | ERR_FATAL;
6370 goto out;
6371 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006372 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006373 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006374
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006375 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006376 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006377 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006378 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006380 goto out;
6381 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006382
6383 proto = protocol_by_family(sk->ss_family);
6384 if (!proto || !proto->connect) {
6385 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6386 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006387 err_code |= ERR_ALERT | ERR_FATAL;
6388 goto out;
6389 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006390
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006391 if (port1 != port2) {
6392 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6393 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006394 err_code |= ERR_ALERT | ERR_FATAL;
6395 goto out;
6396 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006397 curproxy->conn_src.tproxy_addr = *sk;
6398 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006399 }
6400 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006401#else /* no TPROXY support */
6402 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006403 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006404 err_code |= ERR_ALERT | ERR_FATAL;
6405 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006406#endif
6407 cur_arg += 2;
6408 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006409 }
6410
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006411 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6412#ifdef SO_BINDTODEVICE
6413 if (!*args[cur_arg + 1]) {
6414 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6415 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006416 err_code |= ERR_ALERT | ERR_FATAL;
6417 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006418 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006419 free(curproxy->conn_src.iface_name);
6420 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6421 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006422 global.last_checks |= LSTCHK_NETADM;
6423#else
6424 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6425 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006426 err_code |= ERR_ALERT | ERR_FATAL;
6427 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006428#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006429 cur_arg += 2;
6430 continue;
6431 }
6432 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006433 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006434 err_code |= ERR_ALERT | ERR_FATAL;
6435 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006438 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6439 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6440 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006441 err_code |= ERR_ALERT | ERR_FATAL;
6442 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006445 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6447 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006451
6452 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006453 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006454 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006455 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006457 }
6458 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006459 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006460 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006461 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006464 }
6465 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006466 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006467 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006468 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006469 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 }
6472 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006473 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006474 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006475 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006476 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 }
6479 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006480 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006481 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006482 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006486 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006487 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006488 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006489 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006491 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006493 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006494 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6496 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006497 err_code |= ERR_ALERT | ERR_FATAL;
6498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500
6501 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006502 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006503 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006504 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506 }
6507 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006508 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006509 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006510 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006511 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 }
6514 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006515 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006516 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006517 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006518 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520 }
6521 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006522 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006523 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006524 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006525 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 }
6528 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006529 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006530 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006531 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006532 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006535 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006536 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006537 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006538 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006539 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006540 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006543 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006544
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 if (curproxy == &defproxy) {
6546 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006547 err_code |= ERR_ALERT | ERR_FATAL;
6548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006550 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006551 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 if (*(args[1]) == 0) {
6554 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006555 err_code |= ERR_ALERT | ERR_FATAL;
6556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006557 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006558
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006559 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006560 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006561 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6562 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006563 err_code |= ERR_ALERT | ERR_FATAL;
6564 goto out;
6565 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006566 err_code |= warnif_cond_conflicts(cond,
6567 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6568 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006569 }
6570 else if (*args[2]) {
6571 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6572 file, linenum, args[0], args[2]);
6573 err_code |= ERR_ALERT | ERR_FATAL;
6574 goto out;
6575 }
6576
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006577 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006578 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006579 wl->s = strdup(args[1]);
6580 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006581 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582 }
6583 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006584 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6586 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006587 err_code |= ERR_ALERT | ERR_FATAL;
6588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006590
Willy Tarreauade5ec42010-01-28 19:33:49 +01006591 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006592 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006593 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006594 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006596 }
6597 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006598 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006599 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006600 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006601 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603 }
6604 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006605 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006606 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006607 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006608 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 }
6611 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006612 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6614 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006615 err_code |= ERR_ALERT | ERR_FATAL;
6616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617 }
6618
Willy Tarreauade5ec42010-01-28 19:33:49 +01006619 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006620 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006621 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006622 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006624 }
6625 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006626 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006627 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006628 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006629 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006631 }
6632 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006633 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006634 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006635 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006636 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006638 }
6639 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006640 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006641
Willy Tarreaubaaee002006-06-26 02:48:02 +02006642 if (curproxy == &defproxy) {
6643 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006644 err_code |= ERR_ALERT | ERR_FATAL;
6645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006646 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006647 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006648 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006649
Willy Tarreaubaaee002006-06-26 02:48:02 +02006650 if (*(args[1]) == 0) {
6651 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006652 err_code |= ERR_ALERT | ERR_FATAL;
6653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006654 }
6655
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006656 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006657 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006658 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6659 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006660 err_code |= ERR_ALERT | ERR_FATAL;
6661 goto out;
6662 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006663 err_code |= warnif_cond_conflicts(cond,
6664 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6665 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006666 }
6667 else if (*args[2]) {
6668 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6669 file, linenum, args[0], args[2]);
6670 err_code |= ERR_ALERT | ERR_FATAL;
6671 goto out;
6672 }
6673
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006674 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006675 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006676 wl->s = strdup(args[1]);
6677 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006678 }
6679 else if (!strcmp(args[0], "errorloc") ||
6680 !strcmp(args[0], "errorloc302") ||
6681 !strcmp(args[0], "errorloc303")) { /* error location */
6682 int errnum, errlen;
6683 char *err;
6684
Willy Tarreau977b8e42006-12-29 14:19:17 +01006685 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006686 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006687
Willy Tarreaubaaee002006-06-26 02:48:02 +02006688 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006689 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006690 err_code |= ERR_ALERT | ERR_FATAL;
6691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006692 }
6693
6694 errnum = atol(args[1]);
6695 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006696 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6697 err = malloc(errlen);
6698 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006699 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006700 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6701 err = malloc(errlen);
6702 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006703 }
6704
Willy Tarreau0f772532006-12-23 20:51:41 +01006705 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6706 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006707 chunk_destroy(&curproxy->errmsg[rc]);
6708 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006709 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006711 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006712
6713 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006714 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6715 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006716 free(err);
6717 }
6718 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006719 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6720 int errnum, errlen, fd;
6721 char *err;
6722 struct stat stat;
6723
6724 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006725 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006726
6727 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006728 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006729 err_code |= ERR_ALERT | ERR_FATAL;
6730 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006731 }
6732
6733 fd = open(args[2], O_RDONLY);
6734 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6735 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6736 file, linenum, args[2], args[1]);
6737 if (fd >= 0)
6738 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006739 err_code |= ERR_ALERT | ERR_FATAL;
6740 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006741 }
6742
Willy Tarreau27a674e2009-08-17 07:23:33 +02006743 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006744 errlen = stat.st_size;
6745 } else {
6746 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006747 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006748 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006749 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006750 }
6751
6752 err = malloc(errlen); /* malloc() must succeed during parsing */
6753 errnum = read(fd, err, errlen);
6754 if (errnum != errlen) {
6755 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6756 file, linenum, args[2], args[1]);
6757 close(fd);
6758 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006759 err_code |= ERR_ALERT | ERR_FATAL;
6760 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006761 }
6762 close(fd);
6763
6764 errnum = atol(args[1]);
6765 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6766 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006767 chunk_destroy(&curproxy->errmsg[rc]);
6768 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006769 break;
6770 }
6771 }
6772
6773 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006774 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6775 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006776 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006777 free(err);
6778 }
6779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006780 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006781 struct cfg_kw_list *kwl;
6782 int index;
6783
6784 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6785 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6786 if (kwl->kw[index].section != CFG_LISTEN)
6787 continue;
6788 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6789 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006790 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006791 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006792 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006793 err_code |= ERR_ALERT | ERR_FATAL;
6794 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006795 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006796 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006797 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006798 err_code |= ERR_WARN;
6799 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006800 }
Willy Tarreau93893792009-07-23 13:19:11 +02006801 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006802 }
6803 }
6804 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006805
Willy Tarreau6daf3432008-01-22 16:44:08 +01006806 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006807 err_code |= ERR_ALERT | ERR_FATAL;
6808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006809 }
Willy Tarreau93893792009-07-23 13:19:11 +02006810 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006811 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006812 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006813}
6814
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006815int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006816cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6817{
6818#ifdef CONFIG_HAP_NS
6819 const char *err;
6820 const char *item = args[0];
6821
6822 if (!strcmp(item, "namespace_list")) {
6823 return 0;
6824 }
6825 else if (!strcmp(item, "namespace")) {
6826 size_t idx = 1;
6827 const char *current;
6828 while (*(current = args[idx++])) {
6829 err = invalid_char(current);
6830 if (err) {
6831 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6832 file, linenum, *err, item, current);
6833 return ERR_ALERT | ERR_FATAL;
6834 }
6835
6836 if (netns_store_lookup(current, strlen(current))) {
6837 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6838 file, linenum, current);
6839 return ERR_ALERT | ERR_FATAL;
6840 }
6841 if (!netns_store_insert(current)) {
6842 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6843 file, linenum, current);
6844 return ERR_ALERT | ERR_FATAL;
6845 }
6846 }
6847 }
6848
6849 return 0;
6850#else
6851 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6852 file, linenum);
6853 return ERR_ALERT | ERR_FATAL;
6854#endif
6855}
6856
6857int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006858cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6859{
6860
6861 int err_code = 0;
6862 const char *err;
6863
6864 if (!strcmp(args[0], "userlist")) { /* new userlist */
6865 struct userlist *newul;
6866
6867 if (!*args[1]) {
6868 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6869 file, linenum, args[0]);
6870 err_code |= ERR_ALERT | ERR_FATAL;
6871 goto out;
6872 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006873 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6874 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006875
6876 err = invalid_char(args[1]);
6877 if (err) {
6878 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6879 file, linenum, *err, args[0], args[1]);
6880 err_code |= ERR_ALERT | ERR_FATAL;
6881 goto out;
6882 }
6883
6884 for (newul = userlist; newul; newul = newul->next)
6885 if (!strcmp(newul->name, args[1])) {
6886 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6887 file, linenum, args[1]);
6888 err_code |= ERR_WARN;
6889 goto out;
6890 }
6891
Vincent Bernat02779b62016-04-03 13:48:43 +02006892 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006893 if (!newul) {
6894 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6895 err_code |= ERR_ALERT | ERR_ABORT;
6896 goto out;
6897 }
6898
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006899 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006900 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006901 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6902 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006903 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006904 goto out;
6905 }
6906
6907 newul->next = userlist;
6908 userlist = newul;
6909
6910 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006911 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006912 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006913 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006914
6915 if (!*args[1]) {
6916 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6917 file, linenum, args[0]);
6918 err_code |= ERR_ALERT | ERR_FATAL;
6919 goto out;
6920 }
6921
6922 err = invalid_char(args[1]);
6923 if (err) {
6924 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6925 file, linenum, *err, args[0], args[1]);
6926 err_code |= ERR_ALERT | ERR_FATAL;
6927 goto out;
6928 }
6929
William Lallemand4ac9f542015-05-28 18:03:51 +02006930 if (!userlist)
6931 goto out;
6932
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006933 for (ag = userlist->groups; ag; ag = ag->next)
6934 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006935 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6936 file, linenum, args[1], userlist->name);
6937 err_code |= ERR_ALERT;
6938 goto out;
6939 }
6940
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006941 ag = calloc(1, sizeof(*ag));
6942 if (!ag) {
6943 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6944 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006945 goto out;
6946 }
6947
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006948 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006949 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006950 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6951 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006952 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006953 goto out;
6954 }
6955
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006956 cur_arg = 2;
6957
6958 while (*args[cur_arg]) {
6959 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006960 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006961 cur_arg += 2;
6962 continue;
6963 } else {
6964 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6965 file, linenum, args[0]);
6966 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006967 free(ag->groupusers);
6968 free(ag->name);
6969 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006970 goto out;
6971 }
6972 }
6973
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006974 ag->next = userlist->groups;
6975 userlist->groups = ag;
6976
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006977 } else if (!strcmp(args[0], "user")) { /* new user */
6978 struct auth_users *newuser;
6979 int cur_arg;
6980
6981 if (!*args[1]) {
6982 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6983 file, linenum, args[0]);
6984 err_code |= ERR_ALERT | ERR_FATAL;
6985 goto out;
6986 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006987 if (!userlist)
6988 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006989
6990 for (newuser = userlist->users; newuser; newuser = newuser->next)
6991 if (!strcmp(newuser->user, args[1])) {
6992 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6993 file, linenum, args[1], userlist->name);
6994 err_code |= ERR_ALERT;
6995 goto out;
6996 }
6997
Vincent Bernat02779b62016-04-03 13:48:43 +02006998 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006999 if (!newuser) {
7000 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
7001 err_code |= ERR_ALERT | ERR_ABORT;
7002 goto out;
7003 }
7004
7005 newuser->user = strdup(args[1]);
7006
7007 newuser->next = userlist->users;
7008 userlist->users = newuser;
7009
7010 cur_arg = 2;
7011
7012 while (*args[cur_arg]) {
7013 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02007014#ifdef CONFIG_HAP_CRYPT
7015 if (!crypt("", args[cur_arg + 1])) {
7016 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
7017 file, linenum, newuser->user);
7018 err_code |= ERR_ALERT | ERR_FATAL;
7019 goto out;
7020 }
7021#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007022 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
7023 file, linenum);
7024 err_code |= ERR_ALERT;
7025#endif
7026 newuser->pass = strdup(args[cur_arg + 1]);
7027 cur_arg += 2;
7028 continue;
7029 } else if (!strcmp(args[cur_arg], "insecure-password")) {
7030 newuser->pass = strdup(args[cur_arg + 1]);
7031 newuser->flags |= AU_O_INSECURE;
7032 cur_arg += 2;
7033 continue;
7034 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007035 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007036 cur_arg += 2;
7037 continue;
7038 } else {
7039 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7040 file, linenum, args[0]);
7041 err_code |= ERR_ALERT | ERR_FATAL;
7042 goto out;
7043 }
7044 }
7045 } else {
7046 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7047 err_code |= ERR_ALERT | ERR_FATAL;
7048 }
7049
7050out:
7051 return err_code;
7052}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007053
Christopher Faulet79bdef32016-11-04 22:36:15 +01007054int
7055cfg_parse_scope(const char *file, int linenum, char *line)
7056{
7057 char *beg, *end, *scope = NULL;
7058 int err_code = 0;
7059 const char *err;
7060
7061 beg = line + 1;
7062 end = strchr(beg, ']');
7063
7064 /* Detect end of scope declaration */
7065 if (!end || end == beg) {
7066 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7067 file, linenum);
7068 err_code |= ERR_ALERT | ERR_FATAL;
7069 goto out;
7070 }
7071
7072 /* Get scope name and check its validity */
7073 scope = my_strndup(beg, end-beg);
7074 err = invalid_char(scope);
7075 if (err) {
7076 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7077 file, linenum, *err);
7078 err_code |= ERR_ALERT | ERR_ABORT;
7079 goto out;
7080 }
7081
7082 /* Be sure to have a scope declaration alone on its line */
7083 line = end+1;
7084 while (isspace((unsigned char)*line))
7085 line++;
7086 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7087 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7088 file, linenum, *line);
7089 err_code |= ERR_ALERT | ERR_ABORT;
7090 goto out;
7091 }
7092
7093 /* We have a valid scope declaration, save it */
7094 free(cfg_scope);
7095 cfg_scope = scope;
7096 scope = NULL;
7097
7098 out:
7099 free(scope);
7100 return err_code;
7101}
7102
Willy Tarreaubaaee002006-06-26 02:48:02 +02007103/*
7104 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007105 * Returns the error code, 0 if OK, or any combination of :
7106 * - ERR_ABORT: must abort ASAP
7107 * - ERR_FATAL: we can continue parsing but not start the service
7108 * - ERR_WARN: a warning has been emitted
7109 * - ERR_ALERT: an alert has been emitted
7110 * Only the two first ones can stop processing, the two others are just
7111 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007112 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007113int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114{
William Lallemand64e84512015-05-12 14:25:37 +02007115 char *thisline;
7116 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007117 FILE *f;
7118 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007119 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007120 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007121 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007122 int readbytes = 0;
7123
7124 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007125 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007126 return -1;
7127 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007128
David Carlier97880bb2016-04-08 10:35:26 +01007129 if ((f=fopen(file,"r")) == NULL) {
7130 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007131 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133
William Lallemandb2f07452015-05-12 14:27:13 +02007134next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007135 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007136 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007137 char *end;
7138 char *args[MAX_LINE_ARGS + 1];
7139 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007140 int dquote = 0; /* double quote */
7141 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007142
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 linenum++;
7144
7145 end = line + strlen(line);
7146
William Lallemand64e84512015-05-12 14:25:37 +02007147 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007148 /* Check if we reached the limit and the last char is not \n.
7149 * Watch out for the last line without the terminating '\n'!
7150 */
William Lallemand64e84512015-05-12 14:25:37 +02007151 char *newline;
7152 int newlinesize = linesize * 2;
7153
7154 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7155 if (newline == NULL) {
7156 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7157 file, linenum);
7158 err_code |= ERR_ALERT | ERR_FATAL;
7159 continue;
7160 }
7161
7162 readbytes = linesize - 1;
7163 linesize = newlinesize;
7164 thisline = newline;
7165 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007166 }
7167
William Lallemand64e84512015-05-12 14:25:37 +02007168 readbytes = 0;
7169
Willy Tarreaubaaee002006-06-26 02:48:02 +02007170 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007171 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007172 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007173
Christopher Faulet79bdef32016-11-04 22:36:15 +01007174
7175 if (*line == '[') {/* This is the begining if a scope */
7176 err_code |= cfg_parse_scope(file, linenum, line);
7177 goto next_line;
7178 }
7179
Willy Tarreaubaaee002006-06-26 02:48:02 +02007180 arg = 0;
7181 args[arg] = line;
7182
7183 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007184 if (*line == '"' && !squote) { /* double quote outside single quotes */
7185 if (dquote)
7186 dquote = 0;
7187 else
7188 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007189 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007190 end--;
7191 }
7192 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7193 if (squote)
7194 squote = 0;
7195 else
7196 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007197 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007198 end--;
7199 }
7200 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007201 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7202 * C equivalent value. Other combinations left unchanged (eg: \1).
7203 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007204 int skip = 0;
7205 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7206 *line = line[1];
7207 skip = 1;
7208 }
7209 else if (line[1] == 'r') {
7210 *line = '\r';
7211 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007213 else if (line[1] == 'n') {
7214 *line = '\n';
7215 skip = 1;
7216 }
7217 else if (line[1] == 't') {
7218 *line = '\t';
7219 skip = 1;
7220 }
7221 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007222 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007223 unsigned char hex1, hex2;
7224 hex1 = toupper(line[2]) - '0';
7225 hex2 = toupper(line[3]) - '0';
7226 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7227 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7228 *line = (hex1<<4) + hex2;
7229 skip = 3;
7230 }
7231 else {
7232 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007233 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007234 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007235 } else if (line[1] == '"') {
7236 *line = '"';
7237 skip = 1;
7238 } else if (line[1] == '\'') {
7239 *line = '\'';
7240 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007241 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7242 *line = '$';
7243 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007244 }
7245 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007246 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 end -= skip;
7248 }
7249 line++;
7250 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007251 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007252 /* end of string, end of loop */
7253 *line = 0;
7254 break;
7255 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007256 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007258 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007259 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007260 line++;
7261 args[++arg] = line;
7262 }
William Lallemandb2f07452015-05-12 14:27:13 +02007263 else if (dquote && *line == '$') {
7264 /* environment variables are evaluated inside double quotes */
7265 char *var_beg;
7266 char *var_end;
7267 char save_char;
7268 char *value;
7269 int val_len;
7270 int newlinesize;
7271 int braces = 0;
7272
7273 var_beg = line + 1;
7274 var_end = var_beg;
7275
7276 if (*var_beg == '{') {
7277 var_beg++;
7278 var_end++;
7279 braces = 1;
7280 }
7281
7282 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7283 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7284 err_code |= ERR_ALERT | ERR_FATAL;
7285 goto next_line; /* skip current line */
7286 }
7287
7288 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7289 var_end++;
7290
7291 save_char = *var_end;
7292 *var_end = '\0';
7293 value = getenv(var_beg);
7294 *var_end = save_char;
7295 val_len = value ? strlen(value) : 0;
7296
7297 if (braces) {
7298 if (*var_end == '}') {
7299 var_end++;
7300 braces = 0;
7301 } else {
7302 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7303 err_code |= ERR_ALERT | ERR_FATAL;
7304 goto next_line; /* skip current line */
7305 }
7306 }
7307
7308 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7309
7310 /* if not enough space in thisline */
7311 if (newlinesize > linesize) {
7312 char *newline;
7313
7314 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7315 if (newline == NULL) {
7316 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7317 err_code |= ERR_ALERT | ERR_FATAL;
7318 goto next_line; /* slip current line */
7319 }
7320 /* recompute pointers if realloc returns a new pointer */
7321 if (newline != thisline) {
7322 int i;
7323 int diff;
7324
7325 for (i = 0; i <= arg; i++) {
7326 diff = args[i] - thisline;
7327 args[i] = newline + diff;
7328 }
7329
7330 diff = var_end - thisline;
7331 var_end = newline + diff;
7332 diff = end - thisline;
7333 end = newline + diff;
7334 diff = line - thisline;
7335 line = newline + diff;
7336 thisline = newline;
7337 }
7338 linesize = newlinesize;
7339 }
7340
7341 /* insert value inside the line */
7342 memmove(line + val_len, var_end, end - var_end + 1);
7343 memcpy(line, value, val_len);
7344 end += val_len - (var_end - line);
7345 line += val_len;
7346 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007347 else {
7348 line++;
7349 }
7350 }
William Lallemandb2f07452015-05-12 14:27:13 +02007351
William Lallemandf9873ba2015-05-05 17:37:14 +02007352 if (dquote) {
7353 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7354 err_code |= ERR_ALERT | ERR_FATAL;
7355 }
7356
7357 if (squote) {
7358 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7359 err_code |= ERR_ALERT | ERR_FATAL;
7360 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007361
7362 /* empty line */
7363 if (!**args)
7364 continue;
7365
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007366 if (*line) {
7367 /* we had to stop due to too many args.
7368 * Let's terminate the string, print the offending part then cut the
7369 * last arg.
7370 */
7371 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7372 line++;
7373 *line = '\0';
7374
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007375 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007376 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007377 err_code |= ERR_ALERT | ERR_FATAL;
7378 args[arg] = line;
7379 }
7380
Willy Tarreau540abe42007-05-02 20:50:16 +02007381 /* zero out remaining args and ensure that at least one entry
7382 * is zeroed out.
7383 */
7384 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007385 args[arg] = line;
7386 }
7387
Willy Tarreau3842f002009-06-14 11:39:52 +02007388 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007389 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007390 char *tmp;
7391
Willy Tarreau3842f002009-06-14 11:39:52 +02007392 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007393 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007394 for (arg=0; *args[arg+1]; arg++)
7395 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007396 *tmp = '\0'; // fix the next arg to \0
7397 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007398 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007399 else if (!strcmp(args[0], "default")) {
7400 kwm = KWM_DEF;
7401 for (arg=0; *args[arg+1]; arg++)
7402 args[arg] = args[arg+1]; // shift args after inversion
7403 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007404
William Lallemand0f99e342011-10-12 17:50:54 +02007405 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7406 strcmp(args[0], "log") != 0) {
7407 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007408 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007409 }
7410
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007411 /* detect section start */
7412 list_for_each_entry(ics, &sections, list) {
7413 if (strcmp(args[0], ics->section_name) == 0) {
7414 cursection = ics->section_name;
7415 cs = ics;
7416 break;
7417 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007418 }
7419
William Lallemandd2ff56d2017-10-16 11:06:50 +02007420 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007421 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007422 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007423 } else {
7424 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007425
William Lallemandd2ff56d2017-10-16 11:06:50 +02007426 if (pcs != cs && pcs && pcs->post_section_parser) {
7427 err_code |= pcs->post_section_parser();
7428 if (err_code & ERR_ABORT)
7429 goto err;
7430 }
7431
7432 err_code |= cs->section_parser(file, linenum, args, kwm);
7433 if (err_code & ERR_ABORT)
7434 goto err;
7435 }
7436 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007437 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007438
7439 if (pcs == cs && pcs && pcs->post_section_parser)
7440 err_code |= pcs->post_section_parser();
7441
7442err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007443 free(cfg_scope);
7444 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007445 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007446 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007447 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007448 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007449}
7450
Willy Tarreau64ab6072014-09-16 12:17:36 +02007451/* This function propagates processes from frontend <from> to backend <to> so
7452 * that it is always guaranteed that a backend pointed to by a frontend is
7453 * bound to all of its processes. After that, if the target is a "listen"
7454 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007455 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007456 * checked first to ensure that <to> is already bound to all processes of
7457 * <from>, there is no risk of looping and we ensure to follow the shortest
7458 * path to the destination.
7459 *
7460 * It is possible to set <to> to NULL for the first call so that the function
7461 * takes care of visiting the initial frontend in <from>.
7462 *
7463 * It is important to note that the function relies on the fact that all names
7464 * have already been resolved.
7465 */
7466void propagate_processes(struct proxy *from, struct proxy *to)
7467{
7468 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007469
7470 if (to) {
7471 /* check whether we need to go down */
7472 if (from->bind_proc &&
7473 (from->bind_proc & to->bind_proc) == from->bind_proc)
7474 return;
7475
7476 if (!from->bind_proc && !to->bind_proc)
7477 return;
7478
7479 to->bind_proc = from->bind_proc ?
7480 (to->bind_proc | from->bind_proc) : 0;
7481
7482 /* now propagate down */
7483 from = to;
7484 }
7485
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007486 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007487 return;
7488
Willy Tarreauf6b70012014-12-18 14:00:43 +01007489 if (from->state == PR_STSTOPPED)
7490 return;
7491
Willy Tarreau64ab6072014-09-16 12:17:36 +02007492 /* default_backend */
7493 if (from->defbe.be)
7494 propagate_processes(from, from->defbe.be);
7495
7496 /* use_backend */
7497 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007498 if (rule->dynamic)
7499 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007500 to = rule->be.backend;
7501 propagate_processes(from, to);
7502 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007503}
7504
Willy Tarreaubb925012009-07-23 13:36:36 +02007505/*
7506 * Returns the error code, 0 if OK, or any combination of :
7507 * - ERR_ABORT: must abort ASAP
7508 * - ERR_FATAL: we can continue parsing but not start the service
7509 * - ERR_WARN: a warning has been emitted
7510 * - ERR_ALERT: an alert has been emitted
7511 * Only the two first ones can stop processing, the two others are just
7512 * indicators.
7513 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007514int check_config_validity()
7515{
7516 int cfgerr = 0;
7517 struct proxy *curproxy = NULL;
7518 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007519 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007520 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007521 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007522 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007523 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007524
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007525 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007526 /*
7527 * Now, check for the integrity of all that we have collected.
7528 */
7529
7530 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007531 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007532
Willy Tarreau193b8c62012-11-22 00:17:38 +01007533 if (!global.tune.max_http_hdr)
7534 global.tune.max_http_hdr = MAX_HTTP_HDR;
7535
7536 if (!global.tune.cookie_len)
7537 global.tune.cookie_len = CAPTURE_LEN;
7538
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007539 if (!global.tune.requri_len)
7540 global.tune.requri_len = REQURI_LEN;
7541
Emeric Brun96fd9262017-07-05 13:33:16 +02007542 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7543
Willy Tarreau193b8c62012-11-22 00:17:38 +01007544 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7545
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007546 /* Post initialisation of the users and groups lists. */
7547 err_code = userlist_postinit();
7548 if (err_code != ERR_NONE)
7549 goto out;
7550
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007551 /* first, we will invert the proxy list order */
7552 curproxy = NULL;
7553 while (proxy) {
7554 struct proxy *next;
7555
7556 next = proxy->next;
7557 proxy->next = curproxy;
7558 curproxy = proxy;
7559 if (!next)
7560 break;
7561 proxy = next;
7562 }
7563
Willy Tarreau419ead82014-09-16 13:41:21 +02007564 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007565 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007566 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007567 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007568 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007569 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007570 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007571 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007572
Willy Tarreau050536d2012-10-04 08:47:34 +02007573 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007574 /* proxy ID not set, use automatic numbering with first
7575 * spare entry starting with next_pxid.
7576 */
7577 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7578 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7579 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007580 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007581 next_pxid++;
7582
Willy Tarreau55ea7572007-06-17 19:56:27 +02007583
Willy Tarreaubaaee002006-06-26 02:48:02 +02007584 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007585 /* ensure we don't keep listeners uselessly bound */
7586 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007587 free((void *)curproxy->table.peers.name);
7588 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007589 continue;
7590 }
7591
Willy Tarreau102df612014-05-07 23:56:38 +02007592 /* Check multi-process mode compatibility for the current proxy */
7593
7594 if (curproxy->bind_proc) {
7595 /* an explicit bind-process was specified, let's check how many
7596 * processes remain.
7597 */
David Carliere6c39412015-07-02 07:00:17 +00007598 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007599
7600 curproxy->bind_proc &= nbits(global.nbproc);
7601 if (!curproxy->bind_proc && nbproc == 1) {
7602 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);
7603 curproxy->bind_proc = 1;
7604 }
7605 else if (!curproxy->bind_proc && nbproc > 1) {
7606 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);
7607 curproxy->bind_proc = 0;
7608 }
7609 }
7610
Willy Tarreau3d209582014-05-09 17:06:11 +02007611 /* check and reduce the bind-proc of each listener */
7612 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7613 unsigned long mask;
7614
Willy Tarreau45a66cc2017-11-24 11:28:00 +01007615 /* HTTP frontends with "h2" as ALPN/NPN will work in
7616 * HTTP/2 and absolutely require buffers 16kB or larger.
7617 */
7618#ifdef USE_OPENSSL
7619 if (curproxy->mode == PR_MODE_HTTP && global.tune.bufsize < 16384) {
7620#ifdef OPENSSL_NPN_NEGOTIATED
7621 /* check NPN */
7622 if (bind_conf->ssl_conf.npn_str && strcmp(bind_conf->ssl_conf.npn_str, "\002h2") == 0) {
7623 Alert("config : HTTP frontend '%s' enables HTTP/2 via NPN at [%s:%d], so global.tune.bufsize must be at least 16384 bytes (%d now).\n",
7624 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
7625 cfgerr++;
7626 }
7627#endif
7628#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7629 /* check ALPN */
7630 if (bind_conf->ssl_conf.alpn_str && strcmp(bind_conf->ssl_conf.alpn_str, "\002h2") == 0) {
7631 Alert("config : HTTP frontend '%s' enables HTTP/2 via ALPN at [%s:%d], so global.tune.bufsize must be at least 16384 bytes (%d now).\n",
7632 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
7633 cfgerr++;
7634 }
7635#endif
7636 } /* HTTP && bufsize < 16384 */
7637#endif
7638
Willy Tarreau3d209582014-05-09 17:06:11 +02007639 if (!bind_conf->bind_proc)
7640 continue;
7641
7642 mask = nbits(global.nbproc);
7643 if (curproxy->bind_proc)
7644 mask &= curproxy->bind_proc;
7645 /* mask cannot be null here thanks to the previous checks */
7646
David Carliere6c39412015-07-02 07:00:17 +00007647 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007648 bind_conf->bind_proc &= mask;
7649
7650 if (!bind_conf->bind_proc && nbproc == 1) {
7651 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",
7652 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7653 bind_conf->bind_proc = mask & ~(mask - 1);
7654 }
7655 else if (!bind_conf->bind_proc && nbproc > 1) {
7656 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",
7657 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7658 bind_conf->bind_proc = 0;
7659 }
7660 }
7661
Willy Tarreauff01a212009-03-15 13:46:16 +01007662 switch (curproxy->mode) {
7663 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007664 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007665 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007666 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7667 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007668 cfgerr++;
7669 }
7670
7671 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007672 Warning("config : servers will be ignored for %s '%s'.\n",
7673 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007674 break;
7675
7676 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007677 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007678 break;
7679
7680 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007681 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007682 break;
7683 }
7684
Willy Tarreauf3934b82015-08-11 11:36:45 +02007685 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7686 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7687 proxy_type_str(curproxy), curproxy->id);
7688 err_code |= ERR_WARN;
7689 }
7690
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007691 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007692 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007693 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007694 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7695 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007696 cfgerr++;
7697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007698#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007699 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007700 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7701 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007702 cfgerr++;
7703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007704#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007705 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007706 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7707 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007708 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007709 }
7710 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007711 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007712 /* If no LB algo is set in a backend, and we're not in
7713 * transparent mode, dispatch mode nor proxy mode, we
7714 * want to use balance roundrobin by default.
7715 */
7716 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7717 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007718 }
7719 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007720
Willy Tarreau1620ec32011-08-06 17:05:02 +02007721 if (curproxy->options & PR_O_DISPATCH)
7722 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7723 else if (curproxy->options & PR_O_HTTP_PROXY)
7724 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7725 else if (curproxy->options & PR_O_TRANSP)
7726 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007727
Willy Tarreau1620ec32011-08-06 17:05:02 +02007728 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7729 if (curproxy->options & PR_O_DISABLE404) {
7730 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7731 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7732 err_code |= ERR_WARN;
7733 curproxy->options &= ~PR_O_DISABLE404;
7734 }
7735 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7736 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7737 "send-state", proxy_type_str(curproxy), curproxy->id);
7738 err_code |= ERR_WARN;
7739 curproxy->options &= ~PR_O2_CHK_SNDST;
7740 }
Willy Tarreauef781042010-01-27 11:53:01 +01007741 }
7742
Simon Horman98637e52014-06-20 12:30:16 +09007743 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7744 if (!global.external_check) {
7745 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7746 curproxy->id, "option external-check");
7747 cfgerr++;
7748 }
7749 if (!curproxy->check_command) {
7750 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7751 curproxy->id, "option external-check");
7752 cfgerr++;
7753 }
7754 }
7755
Simon Horman64e34162015-02-06 11:11:57 +09007756 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007757 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7758 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007759 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7760 "'email-alert myhostname', or 'email-alert to' "
7761 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007762 "to be present).\n",
7763 proxy_type_str(curproxy), curproxy->id);
7764 err_code |= ERR_WARN;
7765 free_email_alert(curproxy);
7766 }
7767 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007768 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007769 }
7770
Simon Horman98637e52014-06-20 12:30:16 +09007771 if (curproxy->check_command) {
7772 int clear = 0;
7773 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7774 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7775 "external-check command", proxy_type_str(curproxy), curproxy->id);
7776 err_code |= ERR_WARN;
7777 clear = 1;
7778 }
7779 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007780 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007781 curproxy->id, "external-check command");
7782 cfgerr++;
7783 }
7784 if (clear) {
7785 free(curproxy->check_command);
7786 curproxy->check_command = NULL;
7787 }
7788 }
7789
7790 if (curproxy->check_path) {
7791 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7792 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7793 "external-check path", proxy_type_str(curproxy), curproxy->id);
7794 err_code |= ERR_WARN;
7795 free(curproxy->check_path);
7796 curproxy->check_path = NULL;
7797 }
7798 }
7799
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007800 /* if a default backend was specified, let's find it */
7801 if (curproxy->defbe.name) {
7802 struct proxy *target;
7803
Willy Tarreauafb39922015-05-26 12:04:09 +02007804 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007805 if (!target) {
7806 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7807 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007808 cfgerr++;
7809 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007810 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7811 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007812 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007813 } else if (target->mode != curproxy->mode &&
7814 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7815
7816 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7817 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7818 curproxy->conf.file, curproxy->conf.line,
7819 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7820 target->conf.file, target->conf.line);
7821 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007822 } else {
7823 free(curproxy->defbe.name);
7824 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007825 /* Update tot_fe_maxconn for a further fullconn's computation */
7826 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007827 /* Emit a warning if this proxy also has some servers */
7828 if (curproxy->srv) {
7829 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7830 curproxy->id);
7831 err_code |= ERR_WARN;
7832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007833 }
7834 }
7835
Emeric Brun3f783572017-01-12 11:21:28 +01007836 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7837 /* Case of listen without default backend
7838 * The curproxy will be its own default backend
7839 * so we update tot_fe_maxconn for a further
7840 * fullconn's computation */
7841 curproxy->tot_fe_maxconn += curproxy->maxconn;
7842 }
7843
Willy Tarreau55ea7572007-06-17 19:56:27 +02007844 /* find the target proxy for 'use_backend' rules */
7845 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007846 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007847 struct logformat_node *node;
7848 char *pxname;
7849
7850 /* Try to parse the string as a log format expression. If the result
7851 * of the parsing is only one entry containing a simple string, then
7852 * it's a standard string corresponding to a static rule, thus the
7853 * parsing is cancelled and be.name is restored to be resolved.
7854 */
7855 pxname = rule->be.name;
7856 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007857 curproxy->conf.args.ctx = ARGC_UBK;
7858 curproxy->conf.args.file = rule->file;
7859 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007860 err = NULL;
7861 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7862 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7863 rule->file, rule->line, pxname, err);
7864 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007865 cfgerr++;
7866 continue;
7867 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007868 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7869
7870 if (!LIST_ISEMPTY(&rule->be.expr)) {
7871 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7872 rule->dynamic = 1;
7873 free(pxname);
7874 continue;
7875 }
7876 /* simple string: free the expression and fall back to static rule */
7877 free(node->arg);
7878 free(node);
7879 }
7880
7881 rule->dynamic = 0;
7882 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007883
Willy Tarreauafb39922015-05-26 12:04:09 +02007884 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007885 if (!target) {
7886 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7887 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007888 cfgerr++;
7889 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007890 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7891 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007892 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007893 } else if (target->mode != curproxy->mode &&
7894 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7895
7896 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7897 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7898 curproxy->conf.file, curproxy->conf.line,
7899 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7900 target->conf.file, target->conf.line);
7901 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007902 } else {
7903 free((void *)rule->be.name);
7904 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007905 /* For each target of switching rules, we update
7906 * their tot_fe_maxconn, except if a previous rule point
7907 * on the same backend or on the default backend */
7908 if (rule->be.backend != curproxy->defbe.be) {
7909 struct switching_rule *swrule;
7910
7911 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7912 if (rule == swrule) {
7913 target->tot_fe_maxconn += curproxy->maxconn;
7914 break;
7915 }
7916 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7917 /* there is multiple ref of this backend */
7918 break;
7919 }
7920 }
7921 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007922 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007923 }
7924
Willy Tarreau64ab6072014-09-16 12:17:36 +02007925 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007926 list_for_each_entry(srule, &curproxy->server_rules, list) {
7927 struct server *target = findserver(curproxy, srule->srv.name);
7928
7929 if (!target) {
7930 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7931 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7932 cfgerr++;
7933 continue;
7934 }
7935 free((void *)srule->srv.name);
7936 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007937 }
7938
Emeric Brunb982a3d2010-01-04 15:45:53 +01007939 /* find the target table for 'stick' rules */
7940 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7941 struct proxy *target;
7942
Emeric Brun1d33b292010-01-04 15:47:17 +01007943 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7944 if (mrule->flags & STK_IS_STORE)
7945 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7946
Emeric Brunb982a3d2010-01-04 15:45:53 +01007947 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007948 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007949 else
7950 target = curproxy;
7951
7952 if (!target) {
7953 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7954 curproxy->id, mrule->table.name);
7955 cfgerr++;
7956 }
7957 else if (target->table.size == 0) {
7958 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7959 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7960 cfgerr++;
7961 }
Willy Tarreau12785782012-04-27 21:37:17 +02007962 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7963 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007964 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7965 cfgerr++;
7966 }
7967 else {
7968 free((void *)mrule->table.name);
7969 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007970 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007971 }
7972 }
7973
7974 /* find the target table for 'store response' rules */
7975 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7976 struct proxy *target;
7977
Emeric Brun1d33b292010-01-04 15:47:17 +01007978 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7979
Emeric Brunb982a3d2010-01-04 15:45:53 +01007980 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007981 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007982 else
7983 target = curproxy;
7984
7985 if (!target) {
7986 Alert("Proxy '%s': unable to find store table '%s'.\n",
7987 curproxy->id, mrule->table.name);
7988 cfgerr++;
7989 }
7990 else if (target->table.size == 0) {
7991 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7992 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7993 cfgerr++;
7994 }
Willy Tarreau12785782012-04-27 21:37:17 +02007995 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7996 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007997 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7998 cfgerr++;
7999 }
8000 else {
8001 free((void *)mrule->table.name);
8002 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02008003 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01008004 }
8005 }
8006
Christopher Faulete4e830d2017-09-18 14:51:41 +02008007 /* check validity for 'tcp-request' layer 4 rules */
8008 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
8009 err = NULL;
8010 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8011 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8012 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01008013 cfgerr++;
8014 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008015 }
8016
Christopher Faulete4e830d2017-09-18 14:51:41 +02008017 /* check validity for 'tcp-request' layer 5 rules */
8018 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
8019 err = NULL;
8020 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8021 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8022 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01008023 cfgerr++;
8024 }
8025 }
8026
Christopher Faulete4e830d2017-09-18 14:51:41 +02008027 /* check validity for 'tcp-request' layer 6 rules */
8028 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8029 err = NULL;
8030 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8031 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8032 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01008033 cfgerr++;
8034 }
8035 }
8036
Christopher Faulete4e830d2017-09-18 14:51:41 +02008037 /* check validity for 'http-request' layer 7 rules */
8038 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
8039 err = NULL;
8040 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8041 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8042 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008043 cfgerr++;
8044 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008045 }
8046
Christopher Faulete4e830d2017-09-18 14:51:41 +02008047 /* check validity for 'http-response' layer 7 rules */
8048 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
8049 err = NULL;
8050 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8051 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8052 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02008053 cfgerr++;
8054 }
Willy Tarreau09448f72014-06-25 18:12:15 +02008055 }
8056
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008057 /* move any "block" rules at the beginning of the http-request rules */
8058 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8059 /* insert block_rules into http_req_rules at the beginning */
8060 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8061 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8062 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8063 curproxy->http_req_rules.n = curproxy->block_rules.n;
8064 LIST_INIT(&curproxy->block_rules);
8065 }
8066
Emeric Brun32da3c42010-09-23 18:39:19 +02008067 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008068 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008069
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008070 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008071 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8072 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008073 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008074 break;
8075 }
8076 }
8077
8078 if (!curpeers) {
8079 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8080 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008081 free((void *)curproxy->table.peers.name);
8082 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008083 cfgerr++;
8084 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008085 else if (curpeers->state == PR_STSTOPPED) {
8086 /* silently disable this peers section */
8087 curproxy->table.peers.p = NULL;
8088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008089 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008090 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8091 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008092 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008093 cfgerr++;
8094 }
8095 }
8096
Simon Horman9dc49962015-01-30 11:22:59 +09008097
8098 if (curproxy->email_alert.mailers.name) {
8099 struct mailers *curmailers = mailers;
8100
8101 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02008102 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09008103 break;
Simon Horman9dc49962015-01-30 11:22:59 +09008104 }
Simon Horman9dc49962015-01-30 11:22:59 +09008105 if (!curmailers) {
8106 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8107 curproxy->id, curproxy->email_alert.mailers.name);
8108 free_email_alert(curproxy);
8109 cfgerr++;
8110 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02008111 else {
8112 err = NULL;
8113 if (init_email_alert(curmailers, curproxy, &err)) {
8114 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8115 free(err);
8116 cfgerr++;
8117 }
8118 }
Simon Horman9dc49962015-01-30 11:22:59 +09008119 }
8120
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008121 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008122 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008123 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8124 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8125 "proxy", curproxy->id);
8126 cfgerr++;
8127 goto out_uri_auth_compat;
8128 }
8129
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008130 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008131 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008132 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008133 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008134
Willy Tarreau95fa4692010-02-01 13:05:50 +01008135 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8136 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008137
8138 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008139 uri_auth_compat_req[i++] = "realm";
8140 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8141 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008142
Willy Tarreau95fa4692010-02-01 13:05:50 +01008143 uri_auth_compat_req[i++] = "unless";
8144 uri_auth_compat_req[i++] = "{";
8145 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8146 uri_auth_compat_req[i++] = "}";
8147 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008148
Willy Tarreauff011f22011-01-06 17:51:27 +01008149 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8150 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008151 cfgerr++;
8152 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008153 }
8154
Willy Tarreauff011f22011-01-06 17:51:27 +01008155 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008156
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008157 if (curproxy->uri_auth->auth_realm) {
8158 free(curproxy->uri_auth->auth_realm);
8159 curproxy->uri_auth->auth_realm = NULL;
8160 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008161
8162 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008163 }
8164out_uri_auth_compat:
8165
Dragan Dosen43885c72015-10-01 13:18:13 +02008166 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008167 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008168 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8169 if (!curproxy->conf.logformat_sd_string) {
8170 /* set the default logformat_sd_string */
8171 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8172 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008173 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008174 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008175 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008176
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008177 /* compile the log format */
8178 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008179 if (curproxy->conf.logformat_string != default_http_log_format &&
8180 curproxy->conf.logformat_string != default_tcp_log_format &&
8181 curproxy->conf.logformat_string != clf_http_log_format)
8182 free(curproxy->conf.logformat_string);
8183 curproxy->conf.logformat_string = NULL;
8184 free(curproxy->conf.lfs_file);
8185 curproxy->conf.lfs_file = NULL;
8186 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008187
8188 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8189 free(curproxy->conf.logformat_sd_string);
8190 curproxy->conf.logformat_sd_string = NULL;
8191 free(curproxy->conf.lfsd_file);
8192 curproxy->conf.lfsd_file = NULL;
8193 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008194 }
8195
Willy Tarreau62a61232013-04-12 18:13:46 +02008196 if (curproxy->conf.logformat_string) {
8197 curproxy->conf.args.ctx = ARGC_LOG;
8198 curproxy->conf.args.file = curproxy->conf.lfs_file;
8199 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008200 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008201 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008202 SMP_VAL_FE_LOG_END, &err)) {
8203 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8204 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8205 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008206 cfgerr++;
8207 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008208 curproxy->conf.args.file = NULL;
8209 curproxy->conf.args.line = 0;
8210 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008211
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008212 if (curproxy->conf.logformat_sd_string) {
8213 curproxy->conf.args.ctx = ARGC_LOGSD;
8214 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8215 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008216 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008217 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 +01008218 SMP_VAL_FE_LOG_END, &err)) {
8219 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8220 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8221 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008222 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008223 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8224 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8225 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8226 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008227 cfgerr++;
8228 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008229 curproxy->conf.args.file = NULL;
8230 curproxy->conf.args.line = 0;
8231 }
8232
Willy Tarreau62a61232013-04-12 18:13:46 +02008233 if (curproxy->conf.uniqueid_format_string) {
8234 curproxy->conf.args.ctx = ARGC_UIF;
8235 curproxy->conf.args.file = curproxy->conf.uif_file;
8236 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008237 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008238 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 +01008239 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8240 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8241 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8242 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008243 cfgerr++;
8244 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008245 curproxy->conf.args.file = NULL;
8246 curproxy->conf.args.line = 0;
8247 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008248
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008249 /* only now we can check if some args remain unresolved.
8250 * This must be done after the users and groups resolution.
8251 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008252 cfgerr += smp_resolve_args(curproxy);
8253 if (!cfgerr)
8254 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008255
Willy Tarreau2738a142006-07-08 17:28:09 +02008256 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008257 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008258 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008259 (!curproxy->timeout.connect ||
8260 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008261 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008262 " | While not properly invalid, you will certainly encounter various problems\n"
8263 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008264 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008265 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008266 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008267 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008268
Willy Tarreau1fa31262007-12-03 00:36:16 +01008269 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8270 * We must still support older configurations, so let's find out whether those
8271 * parameters have been set or must be copied from contimeouts.
8272 */
8273 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008274 if (!curproxy->timeout.tarpit ||
8275 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008276 /* tarpit timeout not set. We search in the following order:
8277 * default.tarpit, curr.connect, default.connect.
8278 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008279 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008280 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008281 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008282 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008283 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008284 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008285 }
8286 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008287 (!curproxy->timeout.queue ||
8288 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008289 /* queue timeout not set. We search in the following order:
8290 * default.queue, curr.connect, default.connect.
8291 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008292 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008293 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008294 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008295 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008296 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008297 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008298 }
8299 }
8300
Willy Tarreau1620ec32011-08-06 17:05:02 +02008301 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008302 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008303 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008304 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008305 }
8306
Willy Tarreau215663d2014-06-13 18:30:23 +02008307 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8308 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8309 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8310 proxy_type_str(curproxy), curproxy->id);
8311 err_code |= ERR_WARN;
8312 }
8313
Willy Tarreau193b8c62012-11-22 00:17:38 +01008314 /* ensure that cookie capture length is not too large */
8315 if (curproxy->capture_len >= global.tune.cookie_len) {
8316 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8317 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8318 err_code |= ERR_WARN;
8319 curproxy->capture_len = global.tune.cookie_len - 1;
8320 }
8321
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008322 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008323 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008324 curproxy->req_cap_pool = create_pool("ptrcap",
8325 curproxy->nb_req_cap * sizeof(char *),
8326 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008327 }
8328
8329 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008330 curproxy->rsp_cap_pool = create_pool("ptrcap",
8331 curproxy->nb_rsp_cap * sizeof(char *),
8332 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008333 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008334
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008335 switch (curproxy->load_server_state_from_file) {
8336 case PR_SRV_STATE_FILE_UNSPEC:
8337 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8338 break;
8339 case PR_SRV_STATE_FILE_GLOBAL:
8340 if (!global.server_state_file) {
8341 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",
8342 curproxy->id);
8343 err_code |= ERR_WARN;
8344 }
8345 break;
8346 }
8347
Willy Tarreaubaaee002006-06-26 02:48:02 +02008348 /* first, we will invert the servers list order */
8349 newsrv = NULL;
8350 while (curproxy->srv) {
8351 struct server *next;
8352
8353 next = curproxy->srv->next;
8354 curproxy->srv->next = newsrv;
8355 newsrv = curproxy->srv;
8356 if (!next)
8357 break;
8358 curproxy->srv = next;
8359 }
8360
Willy Tarreau17edc812014-01-03 12:14:34 +01008361 /* Check that no server name conflicts. This causes trouble in the stats.
8362 * We only emit a warning for the first conflict affecting each server,
8363 * in order to avoid combinatory explosion if all servers have the same
8364 * name. We do that only for servers which do not have an explicit ID,
8365 * because these IDs were made also for distinguishing them and we don't
8366 * want to annoy people who correctly manage them.
8367 */
8368 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8369 struct server *other_srv;
8370
8371 if (newsrv->puid)
8372 continue;
8373
8374 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8375 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8376 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8377 newsrv->conf.file, newsrv->conf.line,
8378 proxy_type_str(curproxy), curproxy->id,
8379 newsrv->id, other_srv->conf.line);
8380 break;
8381 }
8382 }
8383 }
8384
Willy Tarreaudd701652010-05-25 23:03:02 +02008385 /* assign automatic UIDs to servers which don't have one yet */
8386 next_id = 1;
8387 newsrv = curproxy->srv;
8388 while (newsrv != NULL) {
8389 if (!newsrv->puid) {
8390 /* server ID not set, use automatic numbering with first
8391 * spare entry starting with next_svid.
8392 */
8393 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8394 newsrv->conf.id.key = newsrv->puid = next_id;
8395 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8396 }
8397 next_id++;
8398 newsrv = newsrv->next;
8399 }
8400
Willy Tarreau20697042007-11-15 23:26:18 +01008401 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008402 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008403
Willy Tarreau62c3be22012-01-20 13:12:32 +01008404 /*
8405 * If this server supports a maxconn parameter, it needs a dedicated
8406 * tasks to fill the emptied slots when a connection leaves.
8407 * Also, resolve deferred tracking dependency if needed.
8408 */
8409 newsrv = curproxy->srv;
8410 while (newsrv != NULL) {
8411 if (newsrv->minconn > newsrv->maxconn) {
8412 /* Only 'minconn' was specified, or it was higher than or equal
8413 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8414 * this will avoid further useless expensive computations.
8415 */
8416 newsrv->maxconn = newsrv->minconn;
8417 } else if (newsrv->maxconn && !newsrv->minconn) {
8418 /* minconn was not specified, so we set it to maxconn */
8419 newsrv->minconn = newsrv->maxconn;
8420 }
8421
Willy Tarreau17d45382016-12-22 21:16:08 +01008422 /* this will also properly set the transport layer for prod and checks */
8423 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8424 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8425 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8426 }
Emeric Brun94324a42012-10-11 14:00:19 +02008427
Willy Tarreau2f075e92013-12-03 11:11:34 +01008428 /* set the check type on the server */
8429 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8430
Willy Tarreau62c3be22012-01-20 13:12:32 +01008431 if (newsrv->trackit) {
8432 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008433 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008434 char *pname, *sname;
8435
8436 pname = newsrv->trackit;
8437 sname = strrchr(pname, '/');
8438
8439 if (sname)
8440 *sname++ = '\0';
8441 else {
8442 sname = pname;
8443 pname = NULL;
8444 }
8445
8446 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008447 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008448 if (!px) {
8449 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8450 proxy_type_str(curproxy), curproxy->id,
8451 newsrv->id, pname);
8452 cfgerr++;
8453 goto next_srv;
8454 }
8455 } else
8456 px = curproxy;
8457
8458 srv = findserver(px, sname);
8459 if (!srv) {
8460 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8461 proxy_type_str(curproxy), curproxy->id,
8462 newsrv->id, sname);
8463 cfgerr++;
8464 goto next_srv;
8465 }
8466
Willy Tarreau32091232014-05-16 13:52:00 +02008467 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8468 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8469 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008470 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008471 "tracking as it does not have any check nor agent enabled.\n",
8472 proxy_type_str(curproxy), curproxy->id,
8473 newsrv->id, px->id, srv->id);
8474 cfgerr++;
8475 goto next_srv;
8476 }
8477
8478 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8479
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008480 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008481 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8482 "belongs to a tracking chain looping back to %s/%s.\n",
8483 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008484 newsrv->id, px->id, srv->id, px->id,
8485 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008486 cfgerr++;
8487 goto next_srv;
8488 }
8489
8490 if (curproxy != px &&
8491 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8492 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8493 "tracking: disable-on-404 option inconsistency.\n",
8494 proxy_type_str(curproxy), curproxy->id,
8495 newsrv->id, px->id, srv->id);
8496 cfgerr++;
8497 goto next_srv;
8498 }
8499
Willy Tarreau62c3be22012-01-20 13:12:32 +01008500 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008501 newsrv->tracknext = srv->trackers;
8502 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008503
8504 free(newsrv->trackit);
8505 newsrv->trackit = NULL;
8506 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008507
Willy Tarreau62c3be22012-01-20 13:12:32 +01008508 next_srv:
8509 newsrv = newsrv->next;
8510 }
8511
Olivier Houchard4e694042017-03-14 20:01:29 +01008512 /*
8513 * Try to generate dynamic cookies for servers now.
8514 * It couldn't be done earlier, since at the time we parsed
8515 * the server line, we may not have known yet that we
8516 * should use dynamic cookies, or the secret key may not
8517 * have been provided yet.
8518 */
8519 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8520 newsrv = curproxy->srv;
8521 while (newsrv != NULL) {
8522 srv_set_dyncookie(newsrv);
8523 newsrv = newsrv->next;
8524 }
8525
8526 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008527 /* We have to initialize the server lookup mechanism depending
8528 * on what LB algorithm was choosen.
8529 */
8530
8531 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8532 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8533 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008534 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8535 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8536 init_server_map(curproxy);
8537 } else {
8538 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8539 fwrr_init_server_groups(curproxy);
8540 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008541 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008542
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008543 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008544 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8545 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8546 fwlc_init_server_tree(curproxy);
8547 } else {
8548 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8549 fas_init_server_tree(curproxy);
8550 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008551 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008552
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008553 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008554 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8555 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8556 chash_init_server_tree(curproxy);
8557 } else {
8558 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8559 init_server_map(curproxy);
8560 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008561 break;
8562 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008563 HA_SPIN_INIT(&curproxy->lbprm.lock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02008564
8565 if (curproxy->options & PR_O_LOGASAP)
8566 curproxy->to_log &= ~LW_BYTES;
8567
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008568 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008569 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8570 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008571 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8572 proxy_type_str(curproxy), curproxy->id);
8573 err_code |= ERR_WARN;
8574 }
8575
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008576 if (curproxy->mode != PR_MODE_HTTP) {
8577 int optnum;
8578
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008579 if (curproxy->uri_auth) {
8580 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8581 proxy_type_str(curproxy), curproxy->id);
8582 err_code |= ERR_WARN;
8583 curproxy->uri_auth = NULL;
8584 }
8585
Willy Tarreaude7dc882017-03-10 11:49:21 +01008586 if (curproxy->capture_name) {
8587 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8588 proxy_type_str(curproxy), curproxy->id);
8589 err_code |= ERR_WARN;
8590 }
8591
8592 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8593 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8594 proxy_type_str(curproxy), curproxy->id);
8595 err_code |= ERR_WARN;
8596 }
8597
8598 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8599 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8600 proxy_type_str(curproxy), curproxy->id);
8601 err_code |= ERR_WARN;
8602 }
8603
8604 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8605 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8606 proxy_type_str(curproxy), curproxy->id);
8607 err_code |= ERR_WARN;
8608 }
8609
8610 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8611 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8612 proxy_type_str(curproxy), curproxy->id);
8613 err_code |= ERR_WARN;
8614 }
8615
Willy Tarreau87cf5142011-08-19 22:57:24 +02008616 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008617 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8618 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8619 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008620 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008621 }
8622
8623 if (curproxy->options & PR_O_ORGTO) {
8624 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8625 "originalto", proxy_type_str(curproxy), curproxy->id);
8626 err_code |= ERR_WARN;
8627 curproxy->options &= ~PR_O_ORGTO;
8628 }
8629
8630 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8631 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8632 (curproxy->cap & cfg_opts[optnum].cap) &&
8633 (curproxy->options & cfg_opts[optnum].val)) {
8634 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8635 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8636 err_code |= ERR_WARN;
8637 curproxy->options &= ~cfg_opts[optnum].val;
8638 }
8639 }
8640
8641 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8642 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8643 (curproxy->cap & cfg_opts2[optnum].cap) &&
8644 (curproxy->options2 & cfg_opts2[optnum].val)) {
8645 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8646 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8647 err_code |= ERR_WARN;
8648 curproxy->options2 &= ~cfg_opts2[optnum].val;
8649 }
8650 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008651
Willy Tarreau29fbe512015-08-20 19:35:14 +02008652#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008653 if (curproxy->conn_src.bind_hdr_occ) {
8654 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008655 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008656 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008657 err_code |= ERR_WARN;
8658 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008659#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008660 }
8661
Willy Tarreaubaaee002006-06-26 02:48:02 +02008662 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008663 * ensure that we're not cross-dressing a TCP server into HTTP.
8664 */
8665 newsrv = curproxy->srv;
8666 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008667 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008668 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8669 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008670 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008671 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008672
Willy Tarreau0cec3312011-10-31 13:49:26 +01008673 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8674 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8675 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8676 err_code |= ERR_WARN;
8677 }
8678
Willy Tarreauc93cd162014-05-13 15:54:22 +02008679 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008680 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8681 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8682 err_code |= ERR_WARN;
8683 }
8684
Willy Tarreau29fbe512015-08-20 19:35:14 +02008685#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008686 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8687 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008688 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 +01008689 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008690 err_code |= ERR_WARN;
8691 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008692#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008693
8694 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8695 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8696 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8697 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8698 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8699 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",
8700 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8701 err_code |= ERR_WARN;
8702 }
8703
8704
8705 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8706 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",
8707 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8708 err_code |= ERR_WARN;
8709 }
8710 }
8711
Willy Tarreau21d2af32008-02-14 20:25:24 +01008712 newsrv = newsrv->next;
8713 }
8714
Willy Tarreaue42bd962014-09-16 16:21:19 +02008715 /* check if we have a frontend with "tcp-request content" looking at L7
8716 * with no inspect-delay
8717 */
8718 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008719 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8720 if (arule->action == ACT_TCP_CAPTURE &&
8721 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008722 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008723 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8724 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008725 break;
8726 }
8727
Christopher Faulete4e830d2017-09-18 14:51:41 +02008728 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008729 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8730 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8731 " This means that these rules will randomly find their contents. This can be fixed by"
8732 " setting the tcp-request inspect-delay.\n",
8733 proxy_type_str(curproxy), curproxy->id);
8734 err_code |= ERR_WARN;
8735 }
8736 }
8737
Christopher Fauletd7c91962015-04-30 11:48:27 +02008738 /* Check filter configuration, if any */
8739 cfgerr += flt_check(curproxy);
8740
Willy Tarreauc1a21672009-08-16 22:37:44 +02008741 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008742 if (!curproxy->accept)
8743 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008744
Willy Tarreauc1a21672009-08-16 22:37:44 +02008745 if (curproxy->tcp_req.inspect_delay ||
8746 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008747 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008748
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008749 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008750 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008751 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008752 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008753
8754 /* both TCP and HTTP must check switching rules */
8755 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008756
8757 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008758 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008759 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8760 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 +01008761 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008762 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8763 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008764 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008765 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008766 }
8767
8768 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008769 if (curproxy->tcp_req.inspect_delay ||
8770 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8771 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8772
Emeric Brun97679e72010-09-23 17:56:44 +02008773 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8774 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8775
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008776 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008777 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008778 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008779 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008780
8781 /* If the backend does requires RDP cookie persistence, we have to
8782 * enable the corresponding analyser.
8783 */
8784 if (curproxy->options2 & PR_O2_RDPC_PRST)
8785 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008786
8787 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008788 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008789 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8790 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 +01008791 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008792 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8793 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008794 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008795 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008796 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008797 }
8798
8799 /***********************************************************/
8800 /* At this point, target names have already been resolved. */
8801 /***********************************************************/
8802
8803 /* Check multi-process mode compatibility */
8804
8805 if (global.nbproc > 1 && global.stats_fe) {
8806 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8807 unsigned long mask;
8808
8809 mask = nbits(global.nbproc);
8810 if (global.stats_fe->bind_proc)
8811 mask &= global.stats_fe->bind_proc;
8812
8813 if (bind_conf->bind_proc)
8814 mask &= bind_conf->bind_proc;
8815
8816 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008817 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008818 break;
8819 }
8820 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8821 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");
8822 }
8823 }
8824
8825 /* Make each frontend inherit bind-process from its listeners when not specified. */
8826 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8827 if (curproxy->bind_proc)
8828 continue;
8829
8830 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8831 unsigned long mask;
8832
Willy Tarreaue428b082015-05-04 21:57:58 +02008833 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008834 curproxy->bind_proc |= mask;
8835 }
8836
8837 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008838 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008839 }
8840
8841 if (global.stats_fe) {
8842 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8843 unsigned long mask;
8844
Cyril Bonté06181952016-02-24 00:14:54 +01008845 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008846 global.stats_fe->bind_proc |= mask;
8847 }
8848 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008849 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008850 }
8851
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008852 /* propagate bindings from frontends to backends. Don't do it if there
8853 * are any fatal errors as we must not call it with unresolved proxies.
8854 */
8855 if (!cfgerr) {
8856 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8857 if (curproxy->cap & PR_CAP_FE)
8858 propagate_processes(curproxy, NULL);
8859 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008860 }
8861
8862 /* Bind each unbound backend to all processes when not specified. */
8863 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8864 if (curproxy->bind_proc)
8865 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008866 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008867 }
8868
8869 /*******************************************************/
8870 /* At this step, all proxies have a non-null bind_proc */
8871 /*******************************************************/
8872
8873 /* perform the final checks before creating tasks */
8874
8875 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8876 struct listener *listener;
8877 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008878
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008879 /* Configure SSL for each bind line.
8880 * Note: if configuration fails at some point, the ->ctx member
8881 * remains NULL so that listeners can later detach.
8882 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008883 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008884 if (bind_conf->xprt->prepare_bind_conf &&
8885 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008886 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008887 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008888
Willy Tarreaue6b98942007-10-29 01:09:36 +01008889 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008890 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008891 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008892 int nbproc;
8893
8894 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008895 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008896 nbits(global.nbproc));
8897
8898 if (!nbproc) /* no intersection between listener and frontend */
8899 nbproc = 1;
8900
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008901 if (!listener->luid) {
8902 /* listener ID not set, use automatic numbering with first
8903 * spare entry starting with next_luid.
8904 */
8905 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8906 listener->conf.id.key = listener->luid = next_id;
8907 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008908 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008909 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008910
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008911 /* enable separate counters */
8912 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008913 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008914 if (!listener->name)
8915 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008916 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008917
Willy Tarreaue6b98942007-10-29 01:09:36 +01008918 if (curproxy->options & PR_O_TCP_NOLING)
8919 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008920 if (!listener->maxconn)
8921 listener->maxconn = curproxy->maxconn;
8922 if (!listener->backlog)
8923 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008924 if (!listener->maxaccept)
8925 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8926
8927 /* we want to have an optimal behaviour on single process mode to
8928 * maximize the work at once, but in multi-process we want to keep
8929 * some fairness between processes, so we target half of the max
8930 * number of events to be balanced over all the processes the proxy
8931 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8932 * used to disable the limit.
8933 */
8934 if (listener->maxaccept > 0) {
8935 if (nbproc > 1)
8936 listener->maxaccept = (listener->maxaccept + 1) / 2;
8937 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8938 }
8939
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008940 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008941 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008942 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008943
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008944 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008945 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008946
Willy Tarreau620408f2016-10-21 16:37:51 +02008947 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8948 listener->options |= LI_O_TCP_L5_RULES;
8949
Willy Tarreaude3041d2010-05-31 10:56:17 +02008950 if (curproxy->mon_mask.s_addr)
8951 listener->options |= LI_O_CHK_MONNET;
8952
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008953 /* smart accept mode is automatic in HTTP mode */
8954 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008955 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008956 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8957 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008958 }
8959
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008960 /* Release unused SSL configs */
8961 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008962 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8963 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008964 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008965
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008966 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008967 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008968 int count, maxproc = 0;
8969
8970 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008971 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008972 if (count > maxproc)
8973 maxproc = count;
8974 }
8975 /* backends have 0, frontends have 1 or more */
8976 if (maxproc != 1)
8977 Warning("Proxy '%s': in multi-process mode, stats will be"
8978 " limited to process assigned to the current request.\n",
8979 curproxy->id);
8980
Willy Tarreau102df612014-05-07 23:56:38 +02008981 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8982 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8983 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008984 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008985 }
Willy Tarreau102df612014-05-07 23:56:38 +02008986 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8987 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8988 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008989 }
8990 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008991
8992 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02008993 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02008994 if (curproxy->task) {
8995 curproxy->task->context = curproxy;
8996 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02008997 } else {
8998 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8999 curproxy->id);
9000 cfgerr++;
9001 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009002 }
9003
Willy Tarreaufbb78422011-06-05 15:38:35 +02009004 /* automatically compute fullconn if not set. We must not do it in the
9005 * loop above because cross-references are not yet fully resolved.
9006 */
9007 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9008 /* If <fullconn> is not set, let's set it to 10% of the sum of
9009 * the possible incoming frontend's maxconns.
9010 */
9011 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009012 /* we have the sum of the maxconns in <total>. We only
9013 * keep 10% of that sum to set the default fullconn, with
9014 * a hard minimum of 1 (to avoid a divide by zero).
9015 */
Emeric Brun3f783572017-01-12 11:21:28 +01009016 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009017 if (!curproxy->fullconn)
9018 curproxy->fullconn = 1;
9019 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009020 }
9021
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009022 /*
9023 * Recount currently required checks.
9024 */
9025
9026 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9027 int optnum;
9028
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009029 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9030 if (curproxy->options & cfg_opts[optnum].val)
9031 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009032
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009033 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9034 if (curproxy->options2 & cfg_opts2[optnum].val)
9035 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009036 }
9037
Willy Tarreau0fca4832015-05-01 19:12:05 +02009038 /* compute the required process bindings for the peers */
9039 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9040 if (curproxy->table.peers.p)
9041 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9042
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009043 if (cfg_peers) {
9044 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009045 struct peer *p, *pb;
9046
Willy Tarreau1e273012015-05-01 19:15:17 +02009047 /* Remove all peers sections which don't have a valid listener,
9048 * which are not used by any table, or which are bound to more
9049 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009050 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009051 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009052 while (*last) {
9053 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009054
9055 if (curpeers->state == PR_STSTOPPED) {
9056 /* the "disabled" keyword was present */
9057 if (curpeers->peers_fe)
9058 stop_proxy(curpeers->peers_fe);
9059 curpeers->peers_fe = NULL;
9060 }
9061 else if (!curpeers->peers_fe) {
9062 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9063 curpeers->id, localpeer);
9064 }
David Carliere6c39412015-07-02 07:00:17 +00009065 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009066 /* either it's totally stopped or too much used */
9067 if (curpeers->peers_fe->bind_proc) {
9068 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009069 "running in different processes (%d different ones). "
9070 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009071 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009072 cfgerr++;
9073 }
9074 stop_proxy(curpeers->peers_fe);
9075 curpeers->peers_fe = NULL;
9076 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009077 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009078 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009079 last = &curpeers->next;
9080 continue;
9081 }
9082
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009083 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009084 p = curpeers->remote;
9085 while (p) {
9086 pb = p->next;
9087 free(p->id);
9088 free(p);
9089 p = pb;
9090 }
9091
9092 /* Destroy and unlink this curpeers section.
9093 * Note: curpeers is backed up into *last.
9094 */
9095 free(curpeers->id);
9096 curpeers = curpeers->next;
9097 free(*last);
9098 *last = curpeers;
9099 }
9100 }
9101
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009102 /* initialize stick-tables on backend capable proxies. This must not
9103 * be done earlier because the data size may be discovered while parsing
9104 * other proxies.
9105 */
9106 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9107 if (curproxy->state == PR_STSTOPPED)
9108 continue;
9109
9110 if (!stktable_init(&curproxy->table)) {
9111 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9112 cfgerr++;
9113 }
9114 }
9115
Simon Horman0d16a402015-01-30 11:22:58 +09009116 if (mailers) {
9117 struct mailers *curmailers = mailers, **last;
9118 struct mailer *m, *mb;
9119
9120 /* Remove all mailers sections which don't have a valid listener.
9121 * This can happen when a mailers section is never referenced.
9122 */
9123 last = &mailers;
9124 while (*last) {
9125 curmailers = *last;
9126 if (curmailers->users) {
9127 last = &curmailers->next;
9128 continue;
9129 }
9130
9131 Warning("Removing incomplete section 'mailers %s'.\n",
9132 curmailers->id);
9133
9134 m = curmailers->mailer_list;
9135 while (m) {
9136 mb = m->next;
9137 free(m->id);
9138 free(m);
9139 m = mb;
9140 }
9141
9142 /* Destroy and unlink this curmailers section.
9143 * Note: curmailers is backed up into *last.
9144 */
9145 free(curmailers->id);
9146 curmailers = curmailers->next;
9147 free(*last);
9148 *last = curmailers;
9149 }
9150 }
9151
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009152 /* Update server_state_file_name to backend name if backend is supposed to use
9153 * a server-state file locally defined and none has been provided */
9154 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9155 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9156 curproxy->server_state_file_name == NULL)
9157 curproxy->server_state_file_name = strdup(curproxy->id);
9158 }
9159
Willy Tarreau34eb6712011-10-24 18:15:04 +02009160 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009161 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009162 MEM_F_SHARED);
9163
William Lallemand48b4bb42017-10-23 14:36:34 +02009164 list_for_each_entry(postparser, &postparsers, list) {
9165 if (postparser->func)
9166 cfgerr += postparser->func();
9167 }
9168
Willy Tarreaubb925012009-07-23 13:36:36 +02009169 if (cfgerr > 0)
9170 err_code |= ERR_ALERT | ERR_FATAL;
9171 out:
9172 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009173}
9174
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009175/*
9176 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9177 * parsing sessions.
9178 */
9179void cfg_register_keywords(struct cfg_kw_list *kwl)
9180{
9181 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9182}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009183
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009184/*
9185 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9186 */
9187void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9188{
9189 LIST_DEL(&kwl->list);
9190 LIST_INIT(&kwl->list);
9191}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009192
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009193/* this function register new section in the haproxy configuration file.
9194 * <section_name> is the name of this new section and <section_parser>
9195 * is the called parser. If two section declaration have the same name,
9196 * only the first declared is used.
9197 */
9198int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009199 int (*section_parser)(const char *, int, char **, int),
9200 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009201{
9202 struct cfg_section *cs;
9203
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009204 list_for_each_entry(cs, &sections, list) {
9205 if (strcmp(cs->section_name, section_name) == 0) {
9206 Alert("register section '%s': already registered.\n", section_name);
9207 return 0;
9208 }
9209 }
9210
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009211 cs = calloc(1, sizeof(*cs));
9212 if (!cs) {
9213 Alert("register section '%s': out of memory.\n", section_name);
9214 return 0;
9215 }
9216
9217 cs->section_name = section_name;
9218 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009219 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009220
9221 LIST_ADDQ(&sections, &cs->list);
9222
9223 return 1;
9224}
9225
William Lallemand48b4bb42017-10-23 14:36:34 +02009226/* this function register a new function which will be called once the haproxy
9227 * configuration file has been parsed. It's useful to check dependencies
9228 * between sections or to resolve items once everything is parsed.
9229 */
9230int cfg_register_postparser(char *name, int (*func)())
9231{
9232 struct cfg_postparser *cp;
9233
9234 cp = calloc(1, sizeof(*cp));
9235 if (!cp) {
9236 Alert("register postparser '%s': out of memory.\n", name);
9237 return 0;
9238 }
9239 cp->name = name;
9240 cp->func = func;
9241
9242 LIST_ADDQ(&postparsers, &cp->list);
9243
9244 return 1;
9245}
9246
Willy Tarreaubaaee002006-06-26 02:48:02 +02009247/*
David Carlier845efb52015-09-25 11:49:18 +01009248 * free all config section entries
9249 */
9250void cfg_unregister_sections(void)
9251{
9252 struct cfg_section *cs, *ics;
9253
9254 list_for_each_entry_safe(cs, ics, &sections, list) {
9255 LIST_DEL(&cs->list);
9256 free(cs);
9257 }
9258}
9259
Christopher Faulet7110b402016-10-26 11:09:44 +02009260void cfg_backup_sections(struct list *backup_sections)
9261{
9262 struct cfg_section *cs, *ics;
9263
9264 list_for_each_entry_safe(cs, ics, &sections, list) {
9265 LIST_DEL(&cs->list);
9266 LIST_ADDQ(backup_sections, &cs->list);
9267 }
9268}
9269
9270void cfg_restore_sections(struct list *backup_sections)
9271{
9272 struct cfg_section *cs, *ics;
9273
9274 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9275 LIST_DEL(&cs->list);
9276 LIST_ADDQ(&sections, &cs->list);
9277 }
9278}
9279
Willy Tarreau659fbf02016-05-26 17:55:28 +02009280__attribute__((constructor))
9281static void cfgparse_init(void)
9282{
9283 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009284 cfg_register_section("listen", cfg_parse_listen, NULL);
9285 cfg_register_section("frontend", cfg_parse_listen, NULL);
9286 cfg_register_section("backend", cfg_parse_listen, NULL);
9287 cfg_register_section("defaults", cfg_parse_listen, NULL);
9288 cfg_register_section("global", cfg_parse_global, NULL);
9289 cfg_register_section("userlist", cfg_parse_users, NULL);
9290 cfg_register_section("peers", cfg_parse_peers, NULL);
9291 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9292 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9293 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009294}
9295
David Carlier845efb52015-09-25 11:49:18 +01009296/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009297 * Local variables:
9298 * c-indent-level: 8
9299 * c-basic-offset: 8
9300 * End:
9301 */