blob: ed74960a3f45ebaa6c8f0477c6ee1a2291fb2344 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020062#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010063#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020064#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020065#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020066#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020067#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010068#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020069#include <proto/lb_fwlc.h>
70#include <proto/lb_fwrr.h>
71#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010076#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020077#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020078#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020079#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020081#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010083#include <proto/task.h>
84#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
86
Willy Tarreauf3c69202006-07-09 16:42:34 +020087/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
88 * ssl-hello-chk option to ensure that the remote server speaks SSL.
89 *
90 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
91 */
92const char sslv3_client_hello_pkt[] = {
93 "\x16" /* ContentType : 0x16 = Hanshake */
94 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
95 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
96 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
97 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
98 "\x03\x00" /* Hello Version : 0x0300 = v3 */
99 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
100 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
101 "\x00" /* Session ID length : empty (no session ID) */
102 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
103 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
104 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
105 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
106 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
107 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
108 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
109 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
110 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
111 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
112 "\x00\x38" "\x00\x39" "\x00\x3A"
113 "\x01" /* Compression Length : 0x01 = 1 byte for types */
114 "\x00" /* Compression Type : 0x00 = NULL compression */
115};
116
Willy Tarreau3842f002009-06-14 11:39:52 +0200117/* various keyword modifiers */
118enum kw_mod {
119 KWM_STD = 0, /* normal */
120 KWM_NO, /* "no" prefixed before the keyword */
121 KWM_DEF, /* "default" prefixed before the keyword */
122};
123
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100124/* permit to store configuration section */
125struct cfg_section {
126 struct list list;
127 char *section_name;
128 int (*section_parser)(const char *, int, char **, int);
William Lallemandd2ff56d2017-10-16 11:06:50 +0200129 int (*post_section_parser)();
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100130};
131
132/* Used to chain configuration sections definitions. This list
133 * stores struct cfg_section
134 */
135struct list sections = LIST_HEAD_INIT(sections);
136
William Lallemand48b4bb42017-10-23 14:36:34 +0200137/* store post configuration parsing */
138
139struct cfg_postparser {
140 struct list list;
141 char *name;
142 int (*func)();
143};
144
145struct list postparsers = LIST_HEAD_INIT(postparsers);
146
Willy Tarreau13943ab2006-12-31 00:24:10 +0100147/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149 const char *name;
150 unsigned int val;
151 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100152 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100154};
155
156/* proxy->options */
157static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100158{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
160 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
161 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
163 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
164 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200166 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200167 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100168 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
170 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
171 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100172 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100173#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100175#else
176 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100177#endif
178
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100179 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100180};
181
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100182/* proxy->options2 */
183static const struct cfg_opt cfg_opts2[] =
184{
185#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
187 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
188 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100189#else
190 { "splice-request", 0, 0, 0, 0 },
191 { "splice-response", 0, 0, 0, 0 },
192 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100193#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100194 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
195 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
196 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
197 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
198 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
199 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
200 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
201 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
202 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400203 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100204 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200205 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200206 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100207 { NULL, 0, 0, 0 }
208};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209
Willy Tarreau6daf3432008-01-22 16:44:08 +0100210static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
212int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100213int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100214char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200216/* List head of all known configuration keywords */
217static struct cfg_kw_list cfg_keywords = {
218 .list = LIST_HEAD_INIT(cfg_keywords.list)
219};
220
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221/*
222 * converts <str> to a list of listeners which are dynamically allocated.
223 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
224 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
225 * - <port> is a numerical port from 1 to 65535 ;
226 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
227 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200228 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
229 * not NULL, it must be a valid pointer to either NULL or a freeable area that
230 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200232int 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 +0200233{
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 int port, end;
236
237 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200238
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 while (next && *next) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200240 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100241 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
243 str = next;
244 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100245 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246 *next++ = 0;
247 }
248
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100249 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200250 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200251 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100252 if (!ss2)
253 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100255 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100256 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100258 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100261 if (!port || !end) {
262 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
263 goto fail;
264 }
265
Emeric Bruned760922010-10-22 17:59:25 +0200266 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200267 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200268 goto fail;
269 }
270
271 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200272 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200273 goto fail;
274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100276 else if (ss2->ss_family == AF_UNSPEC) {
277 socklen_t addr_len;
278
279 /* We want to attach to an already bound fd whose number
280 * is in the addr part of ss2 when cast to sockaddr_in.
281 * Note that by definition there is a single listener.
282 * We still have to determine the address family to
283 * register the correct protocol.
284 */
285 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
286 addr_len = sizeof(*ss2);
287 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
288 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
289 goto fail;
290 }
291
292 port = end = get_host_port(ss2);
293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100295 /* OK the address looks correct */
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200296 if (!create_listeners(bind_conf, ss2, port, end, fd, err)) {
297 memprintf(err, "%s for address '%s'.\n", *err, str);
298 goto fail;
299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300 } /* end while(next) */
301 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200302 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 fail:
304 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200305 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306}
307
William Lallemand6e62fb62015-04-28 16:55:23 +0200308/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100309 * Report an error in <msg> when there are too many arguments. This version is
310 * intended to be used by keyword parsers so that the message will be included
311 * into the general error message. The index is the current keyword in args.
312 * Return 0 if the number of argument is correct, otherwise build a message and
313 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
314 * message may also be null, it will simply not be produced (useful to check only).
315 * <msg> and <err_code> are only affected on error.
316 */
317int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
318{
319 int i;
320
321 if (!*args[index + maxarg + 1])
322 return 0;
323
324 if (msg) {
325 *msg = NULL;
326 memprintf(msg, "%s", args[0]);
327 for (i = 1; i <= index; i++)
328 memprintf(msg, "%s %s", *msg, args[i]);
329
330 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
331 }
332 if (err_code)
333 *err_code |= ERR_ALERT | ERR_FATAL;
334
335 return 1;
336}
337
338/*
339 * same as too_many_args_idx with a 0 index
340 */
341int too_many_args(int maxarg, char **args, char **msg, int *err_code)
342{
343 return too_many_args_idx(maxarg, 0, args, msg, err_code);
344}
345
346/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200347 * Report a fatal Alert when there is too much arguments
348 * The index is the current keyword in args
349 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
350 * Fill err_code with an ERR_ALERT and an ERR_FATAL
351 */
352int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
353{
354 char *kw = NULL;
355 int i;
356
357 if (!*args[index + maxarg + 1])
358 return 0;
359
360 memprintf(&kw, "%s", args[0]);
361 for (i = 1; i <= index; i++) {
362 memprintf(&kw, "%s %s", kw, args[i]);
363 }
364
365 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
366 free(kw);
367 *err_code |= ERR_ALERT | ERR_FATAL;
368 return 1;
369}
370
371/*
372 * same as alertif_too_many_args_idx with a 0 index
373 */
374int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
375{
376 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
377}
378
Willy Tarreau620408f2016-10-21 16:37:51 +0200379/* Report a warning if a rule is placed after a 'tcp-request session' rule.
380 * Return 1 if the warning has been emitted, otherwise 0.
381 */
382int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
383{
384 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
385 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
386 file, line, arg);
387 return 1;
388 }
389 return 0;
390}
391
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200392/* Report a warning if a rule is placed after a 'tcp-request content' rule.
393 * Return 1 if the warning has been emitted, otherwise 0.
394 */
395int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
396{
397 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
398 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
399 file, line, arg);
400 return 1;
401 }
402 return 0;
403}
404
Willy Tarreau61d18892009-03-31 10:49:21 +0200405/* Report a warning if a rule is placed after a 'block' rule.
406 * Return 1 if the warning has been emitted, otherwise 0.
407 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200410 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200411 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
412 file, line, arg);
413 return 1;
414 }
415 return 0;
416}
417
Willy Tarreau5002f572014-04-23 01:32:02 +0200418/* Report a warning if a rule is placed after an 'http_request' rule.
419 * Return 1 if the warning has been emitted, otherwise 0.
420 */
421int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
422{
423 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
424 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
425 file, line, arg);
426 return 1;
427 }
428 return 0;
429}
430
Willy Tarreau61d18892009-03-31 10:49:21 +0200431/* Report a warning if a rule is placed after a reqrewrite rule.
432 * Return 1 if the warning has been emitted, otherwise 0.
433 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100434int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200435{
436 if (proxy->req_exp) {
437 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
438 file, line, arg);
439 return 1;
440 }
441 return 0;
442}
443
444/* Report a warning if a rule is placed after a reqadd rule.
445 * Return 1 if the warning has been emitted, otherwise 0.
446 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100447int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200448{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100449 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200450 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
451 file, line, arg);
452 return 1;
453 }
454 return 0;
455}
456
457/* Report a warning if a rule is placed after a redirect rule.
458 * Return 1 if the warning has been emitted, otherwise 0.
459 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100460int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200461{
462 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
463 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
464 file, line, arg);
465 return 1;
466 }
467 return 0;
468}
469
470/* Report a warning if a rule is placed after a 'use_backend' rule.
471 * Return 1 if the warning has been emitted, otherwise 0.
472 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100473int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200474{
475 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
476 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
477 file, line, arg);
478 return 1;
479 }
480 return 0;
481}
482
Willy Tarreauee445d92014-04-23 01:39:04 +0200483/* Report a warning if a rule is placed after a 'use-server' rule.
484 * Return 1 if the warning has been emitted, otherwise 0.
485 */
486int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
487{
488 if (!LIST_ISEMPTY(&proxy->server_rules)) {
489 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
490 file, line, arg);
491 return 1;
492 }
493 return 0;
494}
495
Willy Tarreaud39ad442016-11-25 15:16:12 +0100496/* report a warning if a redirect rule is dangerously placed */
497int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200498{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100499 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200500 warnif_rule_after_use_server(proxy, file, line, arg);
501}
502
Willy Tarreaud39ad442016-11-25 15:16:12 +0100503/* report a warning if a reqadd rule is dangerously placed */
504int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200505{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100506 return warnif_rule_after_redirect(proxy, file, line, arg) ||
507 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200508}
509
Willy Tarreaud39ad442016-11-25 15:16:12 +0100510/* report a warning if a reqxxx rule is dangerously placed */
511int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200512{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100513 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
514 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200515}
516
517/* report a warning if an http-request rule is dangerously placed */
518int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
519{
Willy Tarreau61d18892009-03-31 10:49:21 +0200520 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100521 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200522}
523
Willy Tarreaud39ad442016-11-25 15:16:12 +0100524/* report a warning if a block rule is dangerously placed */
525int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200526{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100527 return warnif_rule_after_http_req(proxy, file, line, arg) ||
528 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200529}
530
Willy Tarreaud39ad442016-11-25 15:16:12 +0100531/* report a warning if a "tcp request content" rule is dangerously placed */
532int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200533{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100534 return warnif_rule_after_block(proxy, file, line, arg) ||
535 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200536}
537
Willy Tarreaud39ad442016-11-25 15:16:12 +0100538/* report a warning if a "tcp request session" rule is dangerously placed */
539int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200540{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100541 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
542 warnif_misplaced_tcp_cont(proxy, file, line, arg);
543}
544
545/* report a warning if a "tcp request connection" rule is dangerously placed */
546int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
547{
548 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
549 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200550}
551
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100552/* Report it if a request ACL condition uses some keywords that are incompatible
553 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
554 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
555 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100556 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100557static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100558{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200560 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100561
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100563 return 0;
564
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100565 acl = acl_cond_conflicts(cond, where);
566 if (acl) {
567 if (acl->name && *acl->name)
568 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
569 file, line, acl->name, sample_ckp_names(where));
570 else
571 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 +0200572 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573 return ERR_WARN;
574 }
575 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100576 return 0;
577
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100578 if (acl->name && *acl->name)
579 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200580 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100581 else
582 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200583 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100584 return ERR_WARN;
585}
586
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 * parse a line in a <global> section. Returns the error code, 0 if OK, or
589 * any combination of :
590 * - ERR_ABORT: must abort ASAP
591 * - ERR_FATAL: we can continue parsing but not start the service
592 * - ERR_WARN: a warning has been emitted
593 * - ERR_ALERT: an alert has been emitted
594 * Only the two first ones can stop processing, the two others are just
595 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200597int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598{
Willy Tarreau058e9072009-07-20 09:30:05 +0200599 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200600 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601
602 if (!strcmp(args[0], "global")) { /* new section */
603 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200604 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 }
607 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200608 if (alertif_too_many_args(0, file, linenum, args, &err_code))
609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 global.mode |= MODE_DAEMON;
611 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200612 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200614 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200615 if (*args[1]) {
616 if (!strcmp(args[1], "exit-on-failure")) {
617 global.tune.options |= GTUNE_EXIT_ONFAILURE;
618 } else {
619 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
622 }
623 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200624 global.mode |= MODE_MWORKER;
625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200627 if (alertif_too_many_args(0, file, linenum, args, &err_code))
628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 global.mode |= MODE_DEBUG;
630 }
631 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200632 if (alertif_too_many_args(0, file, linenum, args, &err_code))
633 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100634 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200636 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200637 if (alertif_too_many_args(0, file, linenum, args, &err_code))
638 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100639 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200642 if (alertif_too_many_args(0, file, linenum, args, &err_code))
643 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100644 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100646 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200647 if (alertif_too_many_args(0, file, linenum, args, &err_code))
648 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100649 global.tune.options &= ~GTUNE_USE_SPLICE;
650 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200651 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200652 if (alertif_too_many_args(0, file, linenum, args, &err_code))
653 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200654 global.tune.options &= ~GTUNE_USE_GAI;
655 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000656 else if (!strcmp(args[0], "noreuseport")) {
657 if (alertif_too_many_args(0, file, linenum, args, &err_code))
658 goto out;
659 global.tune.options &= ~GTUNE_USE_REUSEPORT;
660 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200662 if (alertif_too_many_args(0, file, linenum, args, &err_code))
663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 global.mode |= MODE_QUIET;
665 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200666 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200667 if (alertif_too_many_args(1, file, linenum, args, &err_code))
668 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200669 if (global.tune.maxpollevents != 0) {
670 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200671 err_code |= ERR_ALERT;
672 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200673 }
674 if (*(args[1]) == 0) {
675 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
677 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200678 }
679 global.tune.maxpollevents = atol(args[1]);
680 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100681 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200682 if (alertif_too_many_args(1, file, linenum, args, &err_code))
683 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100684 if (global.tune.maxaccept != 0) {
685 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT;
687 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100688 }
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100693 }
694 global.tune.maxaccept = atol(args[1]);
695 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200696 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200697 if (alertif_too_many_args(1, file, linenum, args, &err_code))
698 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.chksize = atol(args[1]);
705 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100706 else if (!strcmp(args[0], "tune.recv_enough")) {
707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
708 goto out;
709 if (*(args[1]) == 0) {
710 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
711 err_code |= ERR_ALERT | ERR_FATAL;
712 goto out;
713 }
714 global.tune.recv_enough = atol(args[1]);
715 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100716 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
718 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.tune.buf_limit = atol(args[1]);
725 if (global.tune.buf_limit) {
726 if (global.tune.buf_limit < 3)
727 global.tune.buf_limit = 3;
728 if (global.tune.buf_limit <= global.tune.reserved_bufs)
729 global.tune.buf_limit = global.tune.reserved_bufs + 1;
730 }
731 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100732 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
734 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740 global.tune.reserved_bufs = atol(args[1]);
741 if (global.tune.reserved_bufs < 2)
742 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100743 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
744 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100745 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200746 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200747 if (alertif_too_many_args(1, file, linenum, args, &err_code))
748 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200749 if (*(args[1]) == 0) {
750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200755 if (global.tune.bufsize <= 0) {
756 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200760 }
761 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
763 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200764 if (*(args[1]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200770 if (global.tune.maxrewrite < 0) {
771 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200775 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100776 else if (!strcmp(args[0], "tune.idletimer")) {
777 unsigned int idle;
778 const char *res;
779
William Lallemand1a748ae2015-05-19 16:37:23 +0200780 if (alertif_too_many_args(1, file, linenum, args, &err_code))
781 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787
788 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
789 if (res) {
790 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
791 file, linenum, *res, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795
796 if (idle > 65535) {
797 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801 global.tune.idle_timer = idle;
802 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100803 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200804 if (alertif_too_many_args(1, file, linenum, args, &err_code))
805 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100806 if (global.tune.client_rcvbuf != 0) {
807 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
808 err_code |= ERR_ALERT;
809 goto out;
810 }
811 if (*(args[1]) == 0) {
812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 global.tune.client_rcvbuf = atol(args[1]);
817 }
818 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
820 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100821 if (global.tune.server_rcvbuf != 0) {
822 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT;
824 goto out;
825 }
826 if (*(args[1]) == 0) {
827 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 global.tune.server_rcvbuf = atol(args[1]);
832 }
833 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200834 if (alertif_too_many_args(1, file, linenum, args, &err_code))
835 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100836 if (global.tune.client_sndbuf != 0) {
837 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT;
839 goto out;
840 }
841 if (*(args[1]) == 0) {
842 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
843 err_code |= ERR_ALERT | ERR_FATAL;
844 goto out;
845 }
846 global.tune.client_sndbuf = atol(args[1]);
847 }
848 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200849 if (alertif_too_many_args(1, file, linenum, args, &err_code))
850 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100851 if (global.tune.server_sndbuf != 0) {
852 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT;
854 goto out;
855 }
856 if (*(args[1]) == 0) {
857 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
858 err_code |= ERR_ALERT | ERR_FATAL;
859 goto out;
860 }
861 global.tune.server_sndbuf = atol(args[1]);
862 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200863 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200864 if (alertif_too_many_args(1, file, linenum, args, &err_code))
865 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200866 if (*(args[1]) == 0) {
867 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870 }
871 global.tune.pipesize = atol(args[1]);
872 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100873 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200874 if (alertif_too_many_args(1, file, linenum, args, &err_code))
875 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100876 if (*(args[1]) == 0) {
877 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 global.tune.cookie_len = atol(args[1]) + 1;
882 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200883 else if (!strcmp(args[0], "tune.http.logurilen")) {
884 if (alertif_too_many_args(1, file, linenum, args, &err_code))
885 goto out;
886 if (*(args[1]) == 0) {
887 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.tune.requri_len = atol(args[1]) + 1;
892 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200893 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200894 if (alertif_too_many_args(1, file, linenum, args, &err_code))
895 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200901 global.tune.max_http_hdr = atoi(args[1]);
902 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
903 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
904 file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200908 }
William Lallemandf3747832012-11-09 12:33:10 +0100909 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200910 if (alertif_too_many_args(1, file, linenum, args, &err_code))
911 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100912 if (*args[1]) {
913 global.tune.comp_maxlevel = atoi(args[1]);
914 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
915 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
916 file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920 } else {
921 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200927 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
928 if (*args[1]) {
929 global.tune.pattern_cache = atoi(args[1]);
930 if (global.tune.pattern_cache < 0) {
931 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
932 file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 } else {
937 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
938 file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200944 if (alertif_too_many_args(1, file, linenum, args, &err_code))
945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200947 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200948 err_code |= ERR_ALERT;
949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
951 if (*(args[1]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100956 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
957 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]);
958 err_code |= ERR_WARN;
959 goto out;
960 }
961
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200964 if (alertif_too_many_args(1, file, linenum, args, &err_code))
965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200967 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200968 err_code |= ERR_ALERT;
969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 if (*(args[1]) == 0) {
972 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT | ERR_FATAL;
974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100976 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
977 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]);
978 err_code |= ERR_WARN;
979 goto out;
980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 }
Simon Horman98637e52014-06-20 12:30:16 +0900982 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200983 if (alertif_too_many_args(0, file, linenum, args, &err_code))
984 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900985 global.external_check = 1;
986 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200987 /* user/group name handling */
988 else if (!strcmp(args[0], "user")) {
989 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200990 if (alertif_too_many_args(1, file, linenum, args, &err_code))
991 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200992 if (global.uid != 0) {
993 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200994 err_code |= ERR_ALERT;
995 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200996 }
997 errno = 0;
998 ha_user = getpwnam(args[1]);
999 if (ha_user != NULL) {
1000 global.uid = (int)ha_user->pw_uid;
1001 }
1002 else {
1003 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 +02001004 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001005 }
1006 }
1007 else if (!strcmp(args[0], "group")) {
1008 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001009 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1010 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001011 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001012 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT;
1014 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001015 }
1016 errno = 0;
1017 ha_group = getgrnam(args[1]);
1018 if (ha_group != NULL) {
1019 global.gid = (int)ha_group->gr_gid;
1020 }
1021 else {
1022 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 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001024 }
1025 }
1026 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001028 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 if (*(args[1]) == 0) {
1031 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 }
1035 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001036 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1037 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1038 file, linenum, args[0], LONGBITS, global.nbproc);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001044 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 if (global.maxconn != 0) {
1047 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT;
1049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 }
1051 if (*(args[1]) == 0) {
1052 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 err_code |= ERR_ALERT | ERR_FATAL;
1054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 }
1056 global.maxconn = atol(args[1]);
1057#ifdef SYSTEM_MAXCONN
1058 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1059 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);
1060 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
1063#endif /* SYSTEM_MAXCONN */
1064 }
Emeric Brun850efd52014-01-29 12:24:34 +01001065 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001066 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1067 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073 if (strcmp(args[1],"none") == 0)
1074 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1075 else if (strcmp(args[1],"required") == 0)
1076 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1077 else {
1078 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
1081 }
1082 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001083 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001086 if (global.cps_lim != 0) {
1087 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT;
1089 goto out;
1090 }
1091 if (*(args[1]) == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096 global.cps_lim = atol(args[1]);
1097 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001098 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001099 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1100 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001101 if (global.sps_lim != 0) {
1102 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1103 err_code |= ERR_ALERT;
1104 goto out;
1105 }
1106 if (*(args[1]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
1110 }
1111 global.sps_lim = atol(args[1]);
1112 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001113 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001114 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1115 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001116 if (global.ssl_lim != 0) {
1117 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1118 err_code |= ERR_ALERT;
1119 goto out;
1120 }
1121 if (*(args[1]) == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
1125 }
1126 global.ssl_lim = atol(args[1]);
1127 }
William Lallemandd85f9172012-11-09 17:05:39 +01001128 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001129 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1130 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001131 if (*(args[1]) == 0) {
1132 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
1135 }
1136 global.comp_rate_lim = atoi(args[1]) * 1024;
1137 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001138 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001139 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1140 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001141 if (global.maxpipes != 0) {
1142 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001143 err_code |= ERR_ALERT;
1144 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001145 }
1146 if (*(args[1]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001150 }
1151 global.maxpipes = atol(args[1]);
1152 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001153 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001154 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1155 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001156 if (*(args[1]) == 0) {
1157 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
1160 }
William Lallemande3a7d992012-11-20 11:25:20 +01001161 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001162 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001163 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001164 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1165 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001166 if (*(args[1]) == 0) {
1167 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1168 err_code |= ERR_ALERT | ERR_FATAL;
1169 goto out;
1170 }
1171 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001172 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001173 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto out;
1176 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001177 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001178
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 if (global.rlimit_nofile != 0) {
1183 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001184 err_code |= ERR_ALERT;
1185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 }
1187 if (*(args[1]) == 0) {
1188 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 }
1192 global.rlimit_nofile = atol(args[1]);
1193 }
1194 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 if (global.chroot != NULL) {
1198 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001199 err_code |= ERR_ALERT;
1200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 }
1202 if (*(args[1]) == 0) {
1203 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 }
1207 global.chroot = strdup(args[1]);
1208 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001209 else if (!strcmp(args[0], "description")) {
1210 int i, len=0;
1211 char *d;
1212
1213 if (!*args[1]) {
1214 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1215 file, linenum, args[0]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218 }
1219
Willy Tarreau348acfe2014-04-14 15:00:39 +02001220 for (i = 1; *args[i]; i++)
1221 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001222
1223 if (global.desc)
1224 free(global.desc);
1225
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001226 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001227
Willy Tarreau348acfe2014-04-14 15:00:39 +02001228 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1229 for (i = 2; *args[i]; i++)
1230 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001231 }
1232 else if (!strcmp(args[0], "node")) {
1233 int i;
1234 char c;
1235
William Lallemand1a748ae2015-05-19 16:37:23 +02001236 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1237 goto out;
1238
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001239 for (i=0; args[1][i]; i++) {
1240 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001241 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1242 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001243 break;
1244 }
1245
1246 if (!i || args[1][i]) {
1247 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1248 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1249 file, linenum, args[0]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253
1254 if (global.node)
1255 free(global.node);
1256
1257 global.node = strdup(args[1]);
1258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001259 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001260 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 if (global.pidfile != NULL) {
1263 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001264 err_code |= ERR_ALERT;
1265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 }
1267 if (*(args[1]) == 0) {
1268 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 }
1272 global.pidfile = strdup(args[1]);
1273 }
Emeric Bruned760922010-10-22 17:59:25 +02001274 else if (!strcmp(args[0], "unix-bind")) {
1275 int cur_arg = 1;
1276 while (*(args[cur_arg])) {
1277 if (!strcmp(args[cur_arg], "prefix")) {
1278 if (global.unix_bind.prefix != NULL) {
1279 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1280 err_code |= ERR_ALERT;
1281 cur_arg += 2;
1282 continue;
1283 }
1284
1285 if (*(args[cur_arg+1]) == 0) {
1286 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1291 cur_arg += 2;
1292 continue;
1293 }
1294
1295 if (!strcmp(args[cur_arg], "mode")) {
1296
1297 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1298 cur_arg += 2;
1299 continue;
1300 }
1301
1302 if (!strcmp(args[cur_arg], "uid")) {
1303
1304 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1305 cur_arg += 2;
1306 continue;
1307 }
1308
1309 if (!strcmp(args[cur_arg], "gid")) {
1310
1311 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1312 cur_arg += 2;
1313 continue;
1314 }
1315
1316 if (!strcmp(args[cur_arg], "user")) {
1317 struct passwd *user;
1318
1319 user = getpwnam(args[cur_arg + 1]);
1320 if (!user) {
1321 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1322 file, linenum, args[0], args[cur_arg + 1 ]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326
1327 global.unix_bind.ux.uid = user->pw_uid;
1328 cur_arg += 2;
1329 continue;
1330 }
1331
1332 if (!strcmp(args[cur_arg], "group")) {
1333 struct group *group;
1334
1335 group = getgrnam(args[cur_arg + 1]);
1336 if (!group) {
1337 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1338 file, linenum, args[0], args[cur_arg + 1 ]);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342
1343 global.unix_bind.ux.gid = group->gr_gid;
1344 cur_arg += 2;
1345 continue;
1346 }
1347
Willy Tarreaub48f9582011-09-05 01:17:06 +02001348 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001349 file, linenum, args[0]);
1350 err_code |= ERR_ALERT | ERR_FATAL;
1351 goto out;
1352 }
1353 }
William Lallemand0f99e342011-10-12 17:50:54 +02001354 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1355 /* delete previous herited or defined syslog servers */
1356 struct logsrv *back;
1357 struct logsrv *tmp;
1358
1359 if (*(args[1]) != 0) {
1360 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363 }
1364
1365 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1366 LIST_DEL(&tmp->list);
1367 free(tmp);
1368 }
1369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001371 struct sockaddr_storage *sk;
1372 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001373 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001374 int arg = 0;
1375 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001376
William Lallemand1a748ae2015-05-19 16:37:23 +02001377 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1378 goto out;
1379
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 if (*(args[1]) == 0 || *(args[2]) == 0) {
1381 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
1383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
William Lallemand0f99e342011-10-12 17:50:54 +02001385
Vincent Bernat02779b62016-04-03 13:48:43 +02001386 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001387
Willy Tarreau18324f52014-06-27 18:10:07 +02001388 /* just after the address, a length may be specified */
1389 if (strcmp(args[arg+2], "len") == 0) {
1390 len = atoi(args[arg+3]);
1391 if (len < 80 || len > 65535) {
1392 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1393 file, linenum, args[arg+3]);
1394 err_code |= ERR_ALERT | ERR_FATAL;
1395 goto out;
1396 }
1397 logsrv->maxlen = len;
1398
1399 /* skip these two args */
1400 arg += 2;
1401 }
1402 else
1403 logsrv->maxlen = MAX_SYSLOG_LEN;
1404
Christopher Faulet084aa962017-08-29 16:54:41 +02001405 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001406 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001407
Dragan Dosen1322d092015-09-22 16:05:32 +02001408 /* after the length, a format may be specified */
1409 if (strcmp(args[arg+2], "format") == 0) {
1410 logsrv->format = get_log_format(args[arg+3]);
1411 if (logsrv->format < 0) {
1412 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1413 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001414 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001415 goto out;
1416 }
1417
1418 /* skip these two args */
1419 arg += 2;
1420 }
1421
David Carlier97880bb2016-04-08 10:35:26 +01001422 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1423 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001424 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001425 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001426
Willy Tarreau18324f52014-06-27 18:10:07 +02001427 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001428 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001429 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001431 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 }
1433
William Lallemand0f99e342011-10-12 17:50:54 +02001434 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001435 if (*(args[arg+3])) {
1436 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001437 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001438 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001439 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001440 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 }
1442 }
1443
William Lallemand0f99e342011-10-12 17:50:54 +02001444 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001445 if (*(args[arg+4])) {
1446 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001447 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001448 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001449 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001450 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001451 }
1452 }
1453
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001454 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001455 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001456 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001457 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001458 free(logsrv);
1459 goto out;
1460 }
1461 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001462
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001463 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001464 if (port1 != port2) {
1465 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1466 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001467 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001468 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001469 goto out;
1470 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001471
William Lallemand0f99e342011-10-12 17:50:54 +02001472 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001473 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001474 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
William Lallemand0f99e342011-10-12 17:50:54 +02001477 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001478 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001479 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1480 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001481
1482 if (global.log_send_hostname != NULL) {
1483 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1484 err_code |= ERR_ALERT;
1485 goto out;
1486 }
1487
1488 if (*(args[1]))
1489 name = args[1];
1490 else
1491 name = hostname;
1492
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001493 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001494 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001495 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001496 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1497 if (global.server_state_base != NULL) {
1498 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1499 err_code |= ERR_ALERT;
1500 goto out;
1501 }
1502
1503 if (!*(args[1])) {
1504 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1505 err_code |= ERR_FATAL;
1506 goto out;
1507 }
1508
1509 global.server_state_base = strdup(args[1]);
1510 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001511 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1512 if (global.server_state_file != NULL) {
1513 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1514 err_code |= ERR_ALERT;
1515 goto out;
1516 }
1517
1518 if (!*(args[1])) {
1519 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1520 err_code |= ERR_FATAL;
1521 goto out;
1522 }
1523
1524 global.server_state_file = strdup(args[1]);
1525 }
Kevinm48936af2010-12-22 16:08:21 +00001526 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001527 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1528 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001529 if (*(args[1]) == 0) {
1530 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001534 chunk_destroy(&global.log_tag);
1535 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001536 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001537 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001538 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1539 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001540 if (global.spread_checks != 0) {
1541 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001542 err_code |= ERR_ALERT;
1543 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001544 }
1545 if (*(args[1]) == 0) {
1546 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001547 err_code |= ERR_ALERT | ERR_FATAL;
1548 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001549 }
1550 global.spread_checks = atol(args[1]);
1551 if (global.spread_checks < 0 || global.spread_checks > 50) {
1552 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001553 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001556 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1557 const char *err;
1558 unsigned int val;
1559
William Lallemand1a748ae2015-05-19 16:37:23 +02001560 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1561 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001562 if (*(args[1]) == 0) {
1563 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
1566 }
1567
1568 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1569 if (err) {
1570 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1571 err_code |= ERR_ALERT | ERR_FATAL;
1572 }
1573 global.max_spread_checks = val;
1574 if (global.max_spread_checks < 0) {
1575 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1576 err_code |= ERR_ALERT | ERR_FATAL;
1577 }
1578 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001579 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1580#ifdef USE_CPU_AFFINITY
1581 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001582 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001583 unsigned long cpus = 0;
1584
1585 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001586 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001587 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001588 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001589 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001590 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001591 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001592 proc = atol(args[1]);
1593 if (proc >= 1 && proc <= LONGBITS)
1594 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001595 }
1596
1597 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001598 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1599 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001600 err_code |= ERR_ALERT | ERR_FATAL;
1601 goto out;
1602 }
1603
1604 cur_arg = 2;
1605 while (*args[cur_arg]) {
1606 unsigned int low, high;
1607
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001608 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001609 char *dash = strchr(args[cur_arg], '-');
1610
1611 low = high = str2uic(args[cur_arg]);
1612 if (dash)
1613 high = str2uic(dash + 1);
1614
1615 if (high < low) {
1616 unsigned int swap = low;
1617 low = high;
1618 high = swap;
1619 }
1620
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001621 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001622 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001623 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
1626 }
1627
1628 while (low <= high)
1629 cpus |= 1UL << low++;
1630 }
1631 else {
1632 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1633 file, linenum, args[0], args[cur_arg]);
1634 err_code |= ERR_ALERT | ERR_FATAL;
1635 goto out;
1636 }
1637 cur_arg++;
1638 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001639 for (i = 0; i < LONGBITS; i++)
1640 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001641 global.cpu_map[i] = cpus;
1642#else
1643 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1644 err_code |= ERR_ALERT | ERR_FATAL;
1645 goto out;
1646#endif
1647 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001648 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1649 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1650 goto out;
1651
1652 if (*(args[2]) == 0) {
1653 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1654 err_code |= ERR_ALERT | ERR_FATAL;
1655 goto out;
1656 }
1657
1658 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1659 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1660 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1661 err_code |= ERR_ALERT | ERR_FATAL;
1662 goto out;
1663 }
1664 }
1665 else if (!strcmp(args[0], "unsetenv")) {
1666 int arg;
1667
1668 if (*(args[1]) == 0) {
1669 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
1672 }
1673
1674 for (arg = 1; *args[arg]; arg++) {
1675 if (unsetenv(args[arg]) != 0) {
1676 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
1679 }
1680 }
1681 }
1682 else if (!strcmp(args[0], "resetenv")) {
1683 extern char **environ;
1684 char **env = environ;
1685
1686 /* args contain variable names to keep, one per argument */
1687 while (*env) {
1688 int arg;
1689
1690 /* look for current variable in among all those we want to keep */
1691 for (arg = 1; *args[arg]; arg++) {
1692 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1693 (*env)[strlen(args[arg])] == '=')
1694 break;
1695 }
1696
1697 /* delete this variable */
1698 if (!*args[arg]) {
1699 char *delim = strchr(*env, '=');
1700
1701 if (!delim || delim - *env >= trash.size) {
1702 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
1705 }
1706
1707 memcpy(trash.str, *env, delim - *env);
1708 trash.str[delim - *env] = 0;
1709
1710 if (unsetenv(trash.str) != 0) {
1711 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
1714 }
1715 }
1716 else
1717 env++;
1718 }
1719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001721 struct cfg_kw_list *kwl;
1722 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001723 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001724
1725 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1726 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1727 if (kwl->kw[index].section != CFG_GLOBAL)
1728 continue;
1729 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001730 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001731 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001732 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001734 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001735 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001736 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001737 err_code |= ERR_WARN;
1738 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001739 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001740 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001741 }
1742 }
1743 }
1744
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001746 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001748
Willy Tarreau058e9072009-07-20 09:30:05 +02001749 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001750 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001751 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752}
1753
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001754void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001756 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 defproxy.mode = PR_MODE_TCP;
1758 defproxy.state = PR_STNEW;
1759 defproxy.maxconn = cfg_maxpconn;
1760 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001761 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001762 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001763
Simon Horman66183002013-02-23 10:16:43 +09001764 defproxy.defsrv.check.inter = DEF_CHKINTR;
1765 defproxy.defsrv.check.fastinter = 0;
1766 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001767 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1768 defproxy.defsrv.agent.fastinter = 0;
1769 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001770 defproxy.defsrv.check.rise = DEF_RISETIME;
1771 defproxy.defsrv.check.fall = DEF_FALLTIME;
1772 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1773 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001774 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001775 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001776 defproxy.defsrv.maxqueue = 0;
1777 defproxy.defsrv.minconn = 0;
1778 defproxy.defsrv.maxconn = 0;
1779 defproxy.defsrv.slowstart = 0;
1780 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1781 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1782 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001783
1784 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001785 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786}
1787
Willy Tarreauade5ec42010-01-28 19:33:49 +01001788
Willy Tarreau63af98d2014-05-18 08:11:41 +02001789/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1790 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1791 * ERR_FATAL in case of error.
1792 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001793static int create_cond_regex_rule(const char *file, int line,
1794 struct proxy *px, int dir, int action, int flags,
1795 const char *cmd, const char *reg, const char *repl,
1796 const char **cond_start)
1797{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001798 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001799 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001800 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001801 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001802 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001803 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001804 int cs;
1805 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001806
1807 if (px == &defproxy) {
1808 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001809 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001810 goto err;
1811 }
1812
1813 if (*reg == 0) {
1814 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001815 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001816 goto err;
1817 }
1818
Christopher Faulet898566e2016-10-26 11:06:28 +02001819 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001820 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001821
Willy Tarreau5321c422010-01-28 20:35:13 +01001822 if (cond_start &&
1823 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001824 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1825 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1826 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001827 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001828 goto err;
1829 }
1830 }
1831 else if (cond_start && **cond_start) {
1832 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1833 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001834 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001835 goto err;
1836 }
1837
Willy Tarreau63af98d2014-05-18 08:11:41 +02001838 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001839 (dir == SMP_OPT_DIR_REQ) ?
1840 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1841 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1842 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001843
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001844 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001845 if (!preg) {
1846 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001847 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001848 goto err;
1849 }
1850
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001851 cs = !(flags & REG_ICASE);
1852 cap = !(flags & REG_NOSUB);
1853 error = NULL;
1854 if (!regex_comp(reg, preg, cs, cap, &error)) {
1855 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1856 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001857 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001858 goto err;
1859 }
1860
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001861 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001862 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001863 if (repl && err) {
1864 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1865 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001866 ret_code |= ERR_ALERT | ERR_FATAL;
1867 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001868 }
1869
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001870 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001871 ret_code |= ERR_WARN;
1872
1873 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001874
Willy Tarreau63af98d2014-05-18 08:11:41 +02001875 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001876 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001877 err:
1878 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001879 free(errmsg);
1880 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001881}
1882
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883/*
William Lallemand51097192015-04-14 16:35:22 +02001884 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001885 * Returns the error code, 0 if OK, or any combination of :
1886 * - ERR_ABORT: must abort ASAP
1887 * - ERR_FATAL: we can continue parsing but not start the service
1888 * - ERR_WARN: a warning has been emitted
1889 * - ERR_ALERT: an alert has been emitted
1890 * Only the two first ones can stop processing, the two others are just
1891 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001893int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1894{
1895 static struct peers *curpeers = NULL;
1896 struct peer *newpeer = NULL;
1897 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001898 struct bind_conf *bind_conf;
1899 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001900 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001901 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001902
1903 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001904 if (!*args[1]) {
1905 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001906 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001907 goto out;
1908 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001909
William Lallemand6e62fb62015-04-28 16:55:23 +02001910 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1911 goto out;
1912
Emeric Brun32da3c42010-09-23 18:39:19 +02001913 err = invalid_char(args[1]);
1914 if (err) {
1915 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1916 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001917 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001918 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001919 }
1920
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001921 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 /*
1923 * If there are two proxies with the same name only following
1924 * combinations are allowed:
1925 */
1926 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001927 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 +02001928 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 }
1931 }
1932
Vincent Bernat02779b62016-04-03 13:48:43 +02001933 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001934 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1935 err_code |= ERR_ALERT | ERR_ABORT;
1936 goto out;
1937 }
1938
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001939 curpeers->next = cfg_peers;
1940 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001941 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001942 curpeers->conf.line = linenum;
1943 curpeers->last_change = now.tv_sec;
1944 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001945 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001946 }
1947 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001948 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001949 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001950 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001951
1952 if (!*args[2]) {
1953 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1954 file, linenum, args[0]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
1959 err = invalid_char(args[1]);
1960 if (err) {
1961 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1962 file, linenum, *err, args[1]);
1963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
1965 }
1966
Vincent Bernat02779b62016-04-03 13:48:43 +02001967 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001968 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1969 err_code |= ERR_ALERT | ERR_ABORT;
1970 goto out;
1971 }
1972
1973 /* the peers are linked backwards first */
1974 curpeers->count++;
1975 newpeer->next = curpeers->remote;
1976 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001977 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001978 newpeer->conf.line = linenum;
1979
1980 newpeer->last_change = now.tv_sec;
1981 newpeer->id = strdup(args[1]);
1982
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001983 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001984 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001985 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001988 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001989
1990 proto = protocol_by_family(sk->ss_family);
1991 if (!proto || !proto->connect) {
1992 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1993 file, linenum, args[0], args[1]);
1994 err_code |= ERR_ALERT | ERR_FATAL;
1995 goto out;
1996 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001997
1998 if (port1 != port2) {
1999 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2000 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
2003 }
2004
Willy Tarreau2aa38802013-02-20 19:20:59 +01002005 if (!port1) {
2006 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2007 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
2010 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002011
Emeric Brun32da3c42010-09-23 18:39:19 +02002012 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002013 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002014 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002015 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002016
Emeric Brun32da3c42010-09-23 18:39:19 +02002017 if (strcmp(newpeer->id, localpeer) == 0) {
2018 /* Current is local peer, it define a frontend */
2019 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002020 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002021
2022 if (!curpeers->peers_fe) {
2023 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2024 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2025 err_code |= ERR_ALERT | ERR_ABORT;
2026 goto out;
2027 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002028
Willy Tarreau237250c2011-07-29 01:49:03 +02002029 init_new_proxy(curpeers->peers_fe);
2030 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002032 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2033 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002034 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002035
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002036 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002037
Willy Tarreau902636f2013-03-10 19:44:48 +01002038 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2039 if (errmsg && *errmsg) {
2040 indent_msg(&errmsg, 2);
2041 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002042 }
2043 else
2044 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2045 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002046 err_code |= ERR_FATAL;
2047 goto out;
2048 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002049
2050 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002051 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002052 l->maxconn = curpeers->peers_fe->maxconn;
2053 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002054 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002055 l->analysers |= curpeers->peers_fe->fe_req_ana;
2056 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002057 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2058 global.maxsock += l->maxconn;
2059 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002060 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002061 else {
2062 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2063 file, linenum, args[0], args[1],
2064 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2065 err_code |= ERR_FATAL;
2066 goto out;
2067 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002068 }
2069 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002070 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2071 curpeers->state = PR_STSTOPPED;
2072 }
2073 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2074 curpeers->state = PR_STNEW;
2075 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002076 else if (*args[0] != 0) {
2077 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
2080 }
2081
2082out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002083 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 return err_code;
2085}
2086
Baptiste Assmann325137d2015-04-13 23:40:55 +02002087/*
2088 * Parse a <resolvers> section.
2089 * Returns the error code, 0 if OK, or any combination of :
2090 * - ERR_ABORT: must abort ASAP
2091 * - ERR_FATAL: we can continue parsing but not start the service
2092 * - ERR_WARN: a warning has been emitted
2093 * - ERR_ALERT: an alert has been emitted
2094 * Only the two first ones can stop processing, the two others are just
2095 * indicators.
2096 */
2097int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2098{
2099 static struct dns_resolvers *curr_resolvers = NULL;
2100 struct dns_nameserver *newnameserver = NULL;
2101 const char *err;
2102 int err_code = 0;
2103 char *errmsg = NULL;
2104
2105 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2106 if (!*args[1]) {
2107 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2108 err_code |= ERR_ALERT | ERR_ABORT;
2109 goto out;
2110 }
2111
2112 err = invalid_char(args[1]);
2113 if (err) {
2114 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2115 file, linenum, *err, args[0], args[1]);
2116 err_code |= ERR_ALERT | ERR_ABORT;
2117 goto out;
2118 }
2119
2120 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2121 /* Error if two resolvers owns the same name */
2122 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2123 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2124 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2125 err_code |= ERR_ALERT | ERR_ABORT;
2126 }
2127 }
2128
Vincent Bernat02779b62016-04-03 13:48:43 +02002129 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002130 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2131 err_code |= ERR_ALERT | ERR_ABORT;
2132 goto out;
2133 }
2134
2135 /* default values */
2136 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2137 curr_resolvers->conf.file = strdup(file);
2138 curr_resolvers->conf.line = linenum;
2139 curr_resolvers->id = strdup(args[1]);
2140 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002141 /* default maximum response size */
2142 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002143 /* default hold period for nx, other, refuse and timeout is 30s */
2144 curr_resolvers->hold.nx = 30000;
2145 curr_resolvers->hold.other = 30000;
2146 curr_resolvers->hold.refused = 30000;
2147 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002148 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002149 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002150 curr_resolvers->hold.valid = 10000;
2151 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002152 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002153 /* default resolution pool size */
2154 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002155 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002156 LIST_INIT(&curr_resolvers->resolution.curr);
2157 LIST_INIT(&curr_resolvers->resolution.wait);
2158 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002159 }
2160 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2161 struct sockaddr_storage *sk;
2162 int port1, port2;
2163 struct protocol *proto;
2164
2165 if (!*args[2]) {
2166 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2167 file, linenum, args[0]);
2168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
2171
2172 err = invalid_char(args[1]);
2173 if (err) {
2174 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2175 file, linenum, *err, args[1]);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179
Baptiste Assmanna315c552015-11-02 22:55:49 +01002180 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2181 /* Error if two resolvers owns the same name */
2182 if (strcmp(newnameserver->id, args[1]) == 0) {
2183 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2184 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 }
2187 }
2188
Vincent Bernat02779b62016-04-03 13:48:43 +02002189 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002190 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2191 err_code |= ERR_ALERT | ERR_ABORT;
2192 goto out;
2193 }
2194
2195 /* the nameservers are linked backward first */
2196 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2197 curr_resolvers->count_nameservers++;
2198 newnameserver->resolvers = curr_resolvers;
2199 newnameserver->conf.file = strdup(file);
2200 newnameserver->conf.line = linenum;
2201 newnameserver->id = strdup(args[1]);
2202
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002203 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002204 if (!sk) {
2205 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
2208 }
2209
2210 proto = protocol_by_family(sk->ss_family);
2211 if (!proto || !proto->connect) {
2212 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2213 file, linenum, args[0], args[1]);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
2216 }
2217
2218 if (port1 != port2) {
2219 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2220 file, linenum, args[0], args[1], args[2]);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002225 if (!port1 && !port2) {
2226 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2227 file, linenum, args[0], args[1]);
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231
Baptiste Assmann325137d2015-04-13 23:40:55 +02002232 newnameserver->addr = *sk;
2233 }
2234 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2235 const char *res;
2236 unsigned int time;
2237
2238 if (!*args[2]) {
2239 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2240 file, linenum, args[0]);
2241 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2246 if (res) {
2247 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2248 file, linenum, *res, args[0]);
2249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
2251 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002252 if (strcmp(args[1], "nx") == 0)
2253 curr_resolvers->hold.nx = time;
2254 else if (strcmp(args[1], "other") == 0)
2255 curr_resolvers->hold.other = time;
2256 else if (strcmp(args[1], "refused") == 0)
2257 curr_resolvers->hold.refused = time;
2258 else if (strcmp(args[1], "timeout") == 0)
2259 curr_resolvers->hold.timeout = time;
2260 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002261 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002262 else if (strcmp(args[1], "obsolete") == 0)
2263 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002264 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002265 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002266 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270
2271 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002272 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002273 int i = 0;
2274
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002275 if (!*args[1]) {
2276 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2277 file, linenum, args[0]);
2278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
2280 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002281
2282 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002283 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2284 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2285 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289
2290 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002291 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002292 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2293 if (!*args[1]) {
2294 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2295 file, linenum, args[0]);
2296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
2298 }
2299 curr_resolvers->resolution_pool_size = atoi(args[1]);
2300 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002301 else if (strcmp(args[0], "resolve_retries") == 0) {
2302 if (!*args[1]) {
2303 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2304 file, linenum, args[0]);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308 curr_resolvers->resolve_retries = atoi(args[1]);
2309 }
2310 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002311 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002312 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2313 file, linenum, args[0]);
2314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
2316 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002317 else if (strcmp(args[1], "retry") == 0) {
2318 const char *res;
2319 unsigned int timeout_retry;
2320
2321 if (!*args[2]) {
2322 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2323 file, linenum, args[0], args[1]);
2324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
2326 }
2327 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2328 if (res) {
2329 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2330 file, linenum, *res, args[0], args[1]);
2331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
2333 }
2334 curr_resolvers->timeout.retry = timeout_retry;
2335 }
2336 else {
2337 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2338 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002342 } /* neither "nameserver" nor "resolvers" */
2343 else if (*args[0] != 0) {
2344 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348
2349 out:
2350 free(errmsg);
2351 return err_code;
2352}
Simon Horman0d16a402015-01-30 11:22:58 +09002353
2354/*
William Lallemand51097192015-04-14 16:35:22 +02002355 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002356 * Returns the error code, 0 if OK, or any combination of :
2357 * - ERR_ABORT: must abort ASAP
2358 * - ERR_FATAL: we can continue parsing but not start the service
2359 * - ERR_WARN: a warning has been emitted
2360 * - ERR_ALERT: an alert has been emitted
2361 * Only the two first ones can stop processing, the two others are just
2362 * indicators.
2363 */
2364int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2365{
2366 static struct mailers *curmailers = NULL;
2367 struct mailer *newmailer = NULL;
2368 const char *err;
2369 int err_code = 0;
2370 char *errmsg = NULL;
2371
2372 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2373 if (!*args[1]) {
2374 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2375 err_code |= ERR_ALERT | ERR_ABORT;
2376 goto out;
2377 }
2378
2379 err = invalid_char(args[1]);
2380 if (err) {
2381 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2382 file, linenum, *err, args[0], args[1]);
2383 err_code |= ERR_ALERT | ERR_ABORT;
2384 goto out;
2385 }
2386
2387 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2388 /*
2389 * If there are two proxies with the same name only following
2390 * combinations are allowed:
2391 */
2392 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002393 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 +09002394 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002396 }
2397 }
2398
Vincent Bernat02779b62016-04-03 13:48:43 +02002399 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2401 err_code |= ERR_ALERT | ERR_ABORT;
2402 goto out;
2403 }
2404
2405 curmailers->next = mailers;
2406 mailers = curmailers;
2407 curmailers->conf.file = strdup(file);
2408 curmailers->conf.line = linenum;
2409 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002410 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2411 * But need enough time so that timeouts don't occur
2412 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002413 }
2414 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2415 struct sockaddr_storage *sk;
2416 int port1, port2;
2417 struct protocol *proto;
2418
2419 if (!*args[2]) {
2420 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2421 file, linenum, args[0]);
2422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
2424 }
2425
2426 err = invalid_char(args[1]);
2427 if (err) {
2428 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2429 file, linenum, *err, args[1]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433
Vincent Bernat02779b62016-04-03 13:48:43 +02002434 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002435 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2436 err_code |= ERR_ALERT | ERR_ABORT;
2437 goto out;
2438 }
2439
2440 /* the mailers are linked backwards first */
2441 curmailers->count++;
2442 newmailer->next = curmailers->mailer_list;
2443 curmailers->mailer_list = newmailer;
2444 newmailer->mailers = curmailers;
2445 newmailer->conf.file = strdup(file);
2446 newmailer->conf.line = linenum;
2447
2448 newmailer->id = strdup(args[1]);
2449
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002450 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002451 if (!sk) {
2452 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
2455 }
2456
2457 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002458 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2459 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002460 file, linenum, args[0], args[1]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
2465 if (port1 != port2) {
2466 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2467 file, linenum, args[0], args[1], args[2]);
2468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
2470 }
2471
2472 if (!port1) {
2473 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2474 file, linenum, args[0], args[1], args[2]);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 newmailer->addr = *sk;
2480 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002481 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002482 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002483 }
2484 else if (strcmp(args[0], "timeout") == 0) {
2485 if (!*args[1]) {
2486 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2487 file, linenum, args[0]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491 else if (strcmp(args[1], "mail") == 0) {
2492 const char *res;
2493 unsigned int timeout_mail;
2494 if (!*args[2]) {
2495 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2496 file, linenum, args[0], args[1]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2501 if (res) {
2502 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2503 file, linenum, *res, args[0]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507 if (timeout_mail <= 0) {
2508 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512 curmailers->timeout.mail = timeout_mail;
2513 } else {
2514 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2515 file, linenum, args[0], args[1]);
2516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
2518 }
2519 }
Simon Horman0d16a402015-01-30 11:22:58 +09002520 else if (*args[0] != 0) {
2521 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525
2526out:
2527 free(errmsg);
2528 return err_code;
2529}
2530
Simon Horman9dc49962015-01-30 11:22:59 +09002531static void free_email_alert(struct proxy *p)
2532{
2533 free(p->email_alert.mailers.name);
2534 p->email_alert.mailers.name = NULL;
2535 free(p->email_alert.from);
2536 p->email_alert.from = NULL;
2537 free(p->email_alert.to);
2538 p->email_alert.to = NULL;
2539 free(p->email_alert.myhostname);
2540 p->email_alert.myhostname = NULL;
2541}
2542
Willy Tarreau3842f002009-06-14 11:39:52 +02002543int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544{
2545 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002546 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002547 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002548 int rc;
2549 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002550 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002551 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002552 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002553 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002554 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555
Willy Tarreau977b8e42006-12-29 14:19:17 +01002556 if (!strcmp(args[0], "listen"))
2557 rc = PR_CAP_LISTEN;
2558 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002559 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002560 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002561 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 else
2563 rc = PR_CAP_NONE;
2564
2565 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 if (!*args[1]) {
2567 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002568 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_ABORT;
2571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002573
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002574 err = invalid_char(args[1]);
2575 if (err) {
2576 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2577 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002579 }
2580
Willy Tarreau8f50b682015-05-26 11:45:02 +02002581 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2582 if (curproxy) {
2583 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2584 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2585 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002587 }
2588
Vincent Bernat02779b62016-04-03 13:48:43 +02002589 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_ABORT;
2592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002594
Willy Tarreau97cb7802010-01-03 20:23:58 +01002595 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 curproxy->next = proxy;
2597 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002598 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2599 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002600 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002602 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002603 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604
William Lallemand6e62fb62015-04-28 16:55:23 +02002605 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2606 if (curproxy->cap & PR_CAP_FE)
2607 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 }
2610
2611 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002612 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002613 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002614
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002617 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002618 curproxy->no_options = defproxy.no_options;
2619 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002620 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002621 curproxy->except_net = defproxy.except_net;
2622 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002623 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002624 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002626 if (defproxy.fwdfor_hdr_len) {
2627 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2628 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2629 }
2630
Willy Tarreaub86db342009-11-30 11:50:16 +01002631 if (defproxy.orgto_hdr_len) {
2632 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2633 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2634 }
2635
Mark Lamourinec2247f02012-01-04 13:02:01 -05002636 if (defproxy.server_id_hdr_len) {
2637 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2638 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2639 }
2640
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641 if (curproxy->cap & PR_CAP_FE) {
2642 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002643 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002644 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645
2646 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002647 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2648 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649
2650 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652
Willy Tarreau977b8e42006-12-29 14:19:17 +01002653 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002654 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002655 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002656 curproxy->fullconn = defproxy.fullconn;
2657 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002658 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002659 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002661 if (defproxy.check_req) {
2662 curproxy->check_req = calloc(1, defproxy.check_len);
2663 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2664 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002665 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002667 if (defproxy.expect_str) {
2668 curproxy->expect_str = strdup(defproxy.expect_str);
2669 if (defproxy.expect_regex) {
2670 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002671 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2672 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002673 }
2674 }
2675
Willy Tarreau67402132012-05-31 20:40:20 +02002676 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002677 if (defproxy.cookie_name)
2678 curproxy->cookie_name = strdup(defproxy.cookie_name);
2679 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002680
2681 if (defproxy.dyncookie_key)
2682 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002683 if (defproxy.cookie_domain)
2684 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002685
Willy Tarreau31936852010-10-06 16:59:56 +02002686 if (defproxy.cookie_maxidle)
2687 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2688
2689 if (defproxy.cookie_maxlife)
2690 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2691
Emeric Brun647caf12009-06-30 17:57:00 +02002692 if (defproxy.rdp_cookie_name)
2693 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2694 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2695
Willy Tarreau01732802007-11-01 22:48:15 +01002696 if (defproxy.url_param_name)
2697 curproxy->url_param_name = strdup(defproxy.url_param_name);
2698 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002699
Benoitaffb4812009-03-25 13:02:10 +01002700 if (defproxy.hh_name)
2701 curproxy->hh_name = strdup(defproxy.hh_name);
2702 curproxy->hh_len = defproxy.hh_len;
2703 curproxy->hh_match_domain = defproxy.hh_match_domain;
2704
Willy Tarreauef9a3602012-12-08 22:29:20 +01002705 if (defproxy.conn_src.iface_name)
2706 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2707 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002708 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002709#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002710 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002711#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002712 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002715 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002716 if (defproxy.capture_name)
2717 curproxy->capture_name = strdup(defproxy.capture_name);
2718 curproxy->capture_namelen = defproxy.capture_namelen;
2719 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721
Willy Tarreau977b8e42006-12-29 14:19:17 +01002722 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002723 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002724 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002725 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002726 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002727 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002728 curproxy->mon_net = defproxy.mon_net;
2729 curproxy->mon_mask = defproxy.mon_mask;
2730 if (defproxy.monitor_uri)
2731 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2732 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002733 if (defproxy.defbe.name)
2734 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002735
2736 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002737 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2738 if (curproxy->conf.logformat_string &&
2739 curproxy->conf.logformat_string != default_http_log_format &&
2740 curproxy->conf.logformat_string != default_tcp_log_format &&
2741 curproxy->conf.logformat_string != clf_http_log_format)
2742 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2743
2744 if (defproxy.conf.lfs_file) {
2745 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2746 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2747 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002748
2749 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2750 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2751 if (curproxy->conf.logformat_sd_string &&
2752 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2753 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2754
2755 if (defproxy.conf.lfsd_file) {
2756 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2757 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2758 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002759 }
2760
2761 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002762 curproxy->timeout.connect = defproxy.timeout.connect;
2763 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002764 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002765 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002766 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002767 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002768 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002769 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002770 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002771 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002772 }
2773
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002775 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002776
2777 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002778 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002779 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002780 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002781 LIST_INIT(&node->list);
2782 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2783 }
2784
Willy Tarreau62a61232013-04-12 18:13:46 +02002785 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2786 if (curproxy->conf.uniqueid_format_string)
2787 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2788
Dragan Dosen43885c72015-10-01 13:18:13 +02002789 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002790
Willy Tarreau62a61232013-04-12 18:13:46 +02002791 if (defproxy.conf.uif_file) {
2792 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2793 curproxy->conf.uif_line = defproxy.conf.uif_line;
2794 }
William Lallemanda73203e2012-03-12 12:48:57 +01002795
2796 /* copy default header unique id */
2797 if (defproxy.header_unique_id)
2798 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2799
William Lallemand82fe75c2012-10-23 10:25:10 +02002800 /* default compression options */
2801 if (defproxy.comp != NULL) {
2802 curproxy->comp = calloc(1, sizeof(struct comp));
2803 curproxy->comp->algos = defproxy.comp->algos;
2804 curproxy->comp->types = defproxy.comp->types;
2805 }
2806
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002808 curproxy->conf.used_listener_id = EB_ROOT;
2809 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002810
Simon Horman98637e52014-06-20 12:30:16 +09002811 if (defproxy.check_path)
2812 curproxy->check_path = strdup(defproxy.check_path);
2813 if (defproxy.check_command)
2814 curproxy->check_command = strdup(defproxy.check_command);
2815
Simon Horman9dc49962015-01-30 11:22:59 +09002816 if (defproxy.email_alert.mailers.name)
2817 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2818 if (defproxy.email_alert.from)
2819 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2820 if (defproxy.email_alert.to)
2821 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2822 if (defproxy.email_alert.myhostname)
2823 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002824 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002825 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002826
Willy Tarreau93893792009-07-23 13:19:11 +02002827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 }
2829 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2830 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002831 /* FIXME-20070101: we should do this too at the end of the
2832 * config parsing to free all default values.
2833 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002834 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2835 err_code |= ERR_ABORT;
2836 goto out;
2837 }
2838
Willy Tarreaua534fea2008-08-03 12:19:50 +02002839 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002840 free(defproxy.check_command);
2841 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002842 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002843 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002844 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002845 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002846 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002847 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002848 free(defproxy.capture_name);
2849 free(defproxy.monitor_uri);
2850 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002851 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002852 free(defproxy.fwdfor_hdr_name);
2853 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002854 free(defproxy.orgto_hdr_name);
2855 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002856 free(defproxy.server_id_hdr_name);
2857 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002858 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002859 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002860 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002861 free(defproxy.expect_regex);
2862 defproxy.expect_regex = NULL;
2863 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002864
Willy Tarreau62a61232013-04-12 18:13:46 +02002865 if (defproxy.conf.logformat_string != default_http_log_format &&
2866 defproxy.conf.logformat_string != default_tcp_log_format &&
2867 defproxy.conf.logformat_string != clf_http_log_format)
2868 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002869
Willy Tarreau62a61232013-04-12 18:13:46 +02002870 free(defproxy.conf.uniqueid_format_string);
2871 free(defproxy.conf.lfs_file);
2872 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002873 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002874 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002875
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002876 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2877 free(defproxy.conf.logformat_sd_string);
2878 free(defproxy.conf.lfsd_file);
2879
Willy Tarreaua534fea2008-08-03 12:19:50 +02002880 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002881 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002882
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 /* we cannot free uri_auth because it might already be used */
2884 init_default_instance();
2885 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002886 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2887 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002888 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
2891 else if (curproxy == NULL) {
2892 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002896
2897 /* update the current file and line being parsed */
2898 curproxy->conf.args.file = curproxy->conf.file;
2899 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002900
2901 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002902 if (!strcmp(args[0], "server") ||
2903 !strcmp(args[0], "default-server") ||
2904 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002905 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2906 if (err_code & ERR_FATAL)
2907 goto out;
2908 }
2909 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002910 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002911 int cur_arg;
2912
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 if (curproxy == &defproxy) {
2914 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002918 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002919 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920
Willy Tarreau24709282013-03-10 21:32:12 +01002921 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002922 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002927
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002928 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002929
2930 /* use default settings for unix sockets */
2931 bind_conf->ux.uid = global.unix_bind.ux.uid;
2932 bind_conf->ux.gid = global.unix_bind.ux.gid;
2933 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002934
2935 /* NOTE: the following line might create several listeners if there
2936 * are comma-separated IPs or port ranges. So all further processing
2937 * will have to be applied to all listeners created after last_listen.
2938 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002939 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2940 if (errmsg && *errmsg) {
2941 indent_msg(&errmsg, 2);
2942 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002943 }
2944 else
2945 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2946 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
2949 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002950
Willy Tarreau4348fad2012-09-20 16:48:07 +02002951 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2952 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002953 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002954 }
2955
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002956 cur_arg = 2;
2957 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002958 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002959 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002960 char *err;
2961
Willy Tarreau26982662012-09-12 23:17:10 +02002962 kw = bind_find_kw(args[cur_arg]);
2963 if (kw) {
2964 char *err = NULL;
2965 int code;
2966
2967 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002968 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2969 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002970 cur_arg += 1 + kw->skip ;
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974
Willy Tarreau4348fad2012-09-20 16:48:07 +02002975 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002976 err_code |= code;
2977
2978 if (code) {
2979 if (err && *err) {
2980 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002981 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002982 }
2983 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002984 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2985 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002986 if (code & ERR_FATAL) {
2987 free(err);
2988 cur_arg += 1 + kw->skip;
2989 goto out;
2990 }
2991 }
2992 free(err);
2993 cur_arg += 1 + kw->skip;
2994 continue;
2995 }
2996
Willy Tarreau8638f482012-09-18 18:01:17 +02002997 err = NULL;
2998 if (!bind_dumped) {
2999 bind_dump_kws(&err);
3000 indent_msg(&err, 4);
3001 bind_dumped = 1;
3002 }
3003
3004 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3005 file, linenum, args[0], args[1], args[cur_arg],
3006 err ? " Registered keywords :" : "", err ? err : "");
3007 free(err);
3008
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003011 }
Willy Tarreau93893792009-07-23 13:19:11 +02003012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
3014 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003015 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3017 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003021 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 /* flush useless bits */
3025 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003028 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003029 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003031
William Lallemanddf1425a2015-04-28 20:17:49 +02003032 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3033 goto out;
3034
Willy Tarreau1c47f852006-07-09 08:22:27 +02003035 if (!*args[1]) {
3036 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003040 }
3041
Willy Tarreaua534fea2008-08-03 12:19:50 +02003042 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003043 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003044 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003045 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003046 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3047
Willy Tarreau93893792009-07-23 13:19:11 +02003048 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003051 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3052 goto out;
3053
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3055 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3056 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3057 else {
3058 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
3062 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003063 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003064 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003065
3066 if (curproxy == &defproxy) {
3067 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3068 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003071 }
3072
William Lallemanddf1425a2015-04-28 20:17:49 +02003073 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3074 goto out;
3075
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003076 if (!*args[1]) {
3077 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3078 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003081 }
3082
3083 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003084 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003085 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003086
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003087 if (curproxy->uuid <= 0) {
3088 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003089 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003092 }
3093
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003094 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3095 if (node) {
3096 struct proxy *target = container_of(node, struct proxy, conf.id);
3097 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3098 file, linenum, proxy_type_str(curproxy), curproxy->id,
3099 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003104 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003105 else if (!strcmp(args[0], "description")) {
3106 int i, len=0;
3107 char *d;
3108
Cyril Bonté99ed3272010-01-24 23:29:44 +01003109 if (curproxy == &defproxy) {
3110 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3111 file, linenum, args[0]);
3112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
3114 }
3115
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003116 if (!*args[1]) {
3117 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3118 file, linenum, args[0]);
3119 return -1;
3120 }
3121
Willy Tarreau348acfe2014-04-14 15:00:39 +02003122 for (i = 1; *args[i]; i++)
3123 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003124
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003125 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003126 curproxy->desc = d;
3127
Willy Tarreau348acfe2014-04-14 15:00:39 +02003128 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3129 for (i = 2; *args[i]; i++)
3130 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003131
3132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003134 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 curproxy->state = PR_STSTOPPED;
3137 }
3138 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003139 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 curproxy->state = PR_STNEW;
3142 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003143 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3144 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003145 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003146
3147 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003148 unsigned int low, high;
3149
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003150 if (strcmp(args[cur_arg], "all") == 0) {
3151 set = 0;
3152 break;
3153 }
3154 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003155 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003156 }
3157 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003158 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003159 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003160 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003161 char *dash = strchr(args[cur_arg], '-');
3162
3163 low = high = str2uic(args[cur_arg]);
3164 if (dash)
3165 high = str2uic(dash + 1);
3166
3167 if (high < low) {
3168 unsigned int swap = low;
3169 low = high;
3170 high = swap;
3171 }
3172
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003173 if (low < 1 || high > LONGBITS) {
3174 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3175 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003178 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003179 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003180 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003181 }
3182 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003183 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3184 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003185 err_code |= ERR_ALERT | ERR_FATAL;
3186 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003187 }
3188 cur_arg++;
3189 }
3190 curproxy->bind_proc = set;
3191 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003192 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003193 if (curproxy == &defproxy) {
3194 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003197 }
3198
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003199 err = invalid_char(args[1]);
3200 if (err) {
3201 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3202 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003204 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003205 }
3206
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003207 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003208 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3209 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003212 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003213 }
3214 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3215
3216 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3217 err_code |= ERR_WARN;
3218
3219 if (*(args[1]) == 0) {
3220 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3221 file, linenum, args[0]);
3222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
3225 free(curproxy->dyncookie_key);
3226 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3229 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230
Willy Tarreau977b8e42006-12-29 14:19:17 +01003231 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003233
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 if (*(args[1]) == 0) {
3235 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3236 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003240
Willy Tarreau67402132012-05-31 20:40:20 +02003241 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003242 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003243 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003244 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 curproxy->cookie_name = strdup(args[1]);
3246 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003247
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 cur_arg = 2;
3249 while (*(args[cur_arg])) {
3250 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003251 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 }
3253 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003254 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 }
3256 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003257 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 }
3259 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003260 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 }
3262 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003263 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003265 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003266 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003269 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003271 else if (!strcmp(args[cur_arg], "httponly")) {
3272 curproxy->ck_opts |= PR_CK_HTTPONLY;
3273 }
3274 else if (!strcmp(args[cur_arg], "secure")) {
3275 curproxy->ck_opts |= PR_CK_SECURE;
3276 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003277 else if (!strcmp(args[cur_arg], "domain")) {
3278 if (!*args[cur_arg + 1]) {
3279 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3280 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003283 }
3284
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003285 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003286 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003287 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3288 " dots nor does not start with a dot."
3289 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003290 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003291 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003292 }
3293
3294 err = invalid_domainchar(args[cur_arg + 1]);
3295 if (err) {
3296 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3297 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003300 }
3301
Willy Tarreau68a897b2009-12-03 23:28:34 +01003302 if (!curproxy->cookie_domain) {
3303 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3304 } else {
3305 /* one domain was already specified, add another one by
3306 * building the string which will be returned along with
3307 * the cookie.
3308 */
3309 char *new_ptr;
3310 int new_len = strlen(curproxy->cookie_domain) +
3311 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3312 new_ptr = malloc(new_len);
3313 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3314 free(curproxy->cookie_domain);
3315 curproxy->cookie_domain = new_ptr;
3316 }
Willy Tarreau31936852010-10-06 16:59:56 +02003317 cur_arg++;
3318 }
3319 else if (!strcmp(args[cur_arg], "maxidle")) {
3320 unsigned int maxidle;
3321 const char *res;
3322
3323 if (!*args[cur_arg + 1]) {
3324 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3325 file, linenum, args[cur_arg]);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
3328 }
3329
3330 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3331 if (res) {
3332 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3333 file, linenum, *res, args[cur_arg]);
3334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
3336 }
3337 curproxy->cookie_maxidle = maxidle;
3338 cur_arg++;
3339 }
3340 else if (!strcmp(args[cur_arg], "maxlife")) {
3341 unsigned int maxlife;
3342 const char *res;
3343
3344 if (!*args[cur_arg + 1]) {
3345 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3346 file, linenum, args[cur_arg]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350
3351 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3352 if (res) {
3353 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3354 file, linenum, *res, args[cur_arg]);
3355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
3357 }
3358 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003359 cur_arg++;
3360 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003361 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003362
3363 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3364 err_code |= ERR_WARN;
3365 curproxy->ck_opts |= PR_CK_DYNAMIC;
3366 }
3367
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003369 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 +02003370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
3374 cur_arg++;
3375 }
Willy Tarreau67402132012-05-31 20:40:20 +02003376 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3378 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 }
3381
Willy Tarreau67402132012-05-31 20:40:20 +02003382 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3384 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003387
Willy Tarreau67402132012-05-31 20:40:20 +02003388 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003389 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3390 file, linenum);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003394 else if (!strcmp(args[0], "email-alert")) {
3395 if (*(args[1]) == 0) {
3396 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3397 file, linenum, args[0]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
3402 if (!strcmp(args[1], "from")) {
3403 if (*(args[1]) == 0) {
3404 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3405 file, linenum, args[1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409 free(curproxy->email_alert.from);
3410 curproxy->email_alert.from = strdup(args[2]);
3411 }
3412 else if (!strcmp(args[1], "mailers")) {
3413 if (*(args[1]) == 0) {
3414 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3415 file, linenum, args[1]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419 free(curproxy->email_alert.mailers.name);
3420 curproxy->email_alert.mailers.name = strdup(args[2]);
3421 }
3422 else if (!strcmp(args[1], "myhostname")) {
3423 if (*(args[1]) == 0) {
3424 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3425 file, linenum, args[1]);
3426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
3428 }
3429 free(curproxy->email_alert.myhostname);
3430 curproxy->email_alert.myhostname = strdup(args[2]);
3431 }
Simon Horman64e34162015-02-06 11:11:57 +09003432 else if (!strcmp(args[1], "level")) {
3433 curproxy->email_alert.level = get_log_level(args[2]);
3434 if (curproxy->email_alert.level < 0) {
3435 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3436 file, linenum, args[1], args[2]);
3437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
3439 }
3440 }
Simon Horman9dc49962015-01-30 11:22:59 +09003441 else if (!strcmp(args[1], "to")) {
3442 if (*(args[1]) == 0) {
3443 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3444 file, linenum, args[1]);
3445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
3447 }
3448 free(curproxy->email_alert.to);
3449 curproxy->email_alert.to = strdup(args[2]);
3450 }
3451 else {
3452 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3453 file, linenum, args[1]);
3454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
3456 }
Simon Horman64e34162015-02-06 11:11:57 +09003457 /* Indicate that the email_alert is at least partially configured */
3458 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003459 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003460 else if (!strcmp(args[0], "external-check")) {
3461 if (*(args[1]) == 0) {
3462 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3463 file, linenum, args[0]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467
3468 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003469 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003470 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003471 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003472 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3473 file, linenum, args[1]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
3477 free(curproxy->check_command);
3478 curproxy->check_command = strdup(args[2]);
3479 }
3480 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003481 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003482 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003483 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003484 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3485 file, linenum, args[1]);
3486 err_code |= ERR_ALERT | ERR_FATAL;
3487 goto out;
3488 }
3489 free(curproxy->check_path);
3490 curproxy->check_path = strdup(args[2]);
3491 }
3492 else {
3493 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3494 file, linenum, args[1]);
3495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
3497 }
3498 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003499 else if (!strcmp(args[0], "persist")) { /* persist */
3500 if (*(args[1]) == 0) {
3501 Alert("parsing [%s:%d] : missing persist method.\n",
3502 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003505 }
3506
3507 if (!strncmp(args[1], "rdp-cookie", 10)) {
3508 curproxy->options2 |= PR_O2_RDPC_PRST;
3509
Emeric Brunb982a3d2010-01-04 15:45:53 +01003510 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003511 const char *beg, *end;
3512
3513 beg = args[1] + 11;
3514 end = strchr(beg, ')');
3515
William Lallemanddf1425a2015-04-28 20:17:49 +02003516 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3517 goto out;
3518
Emeric Brun647caf12009-06-30 17:57:00 +02003519 if (!end || end == beg) {
3520 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3521 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003524 }
3525
3526 free(curproxy->rdp_cookie_name);
3527 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3528 curproxy->rdp_cookie_len = end-beg;
3529 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003530 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003531 free(curproxy->rdp_cookie_name);
3532 curproxy->rdp_cookie_name = strdup("msts");
3533 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3534 }
3535 else { /* syntax */
3536 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3537 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003540 }
3541 }
3542 else {
3543 Alert("parsing [%s:%d] : unknown persist method.\n",
3544 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003547 }
3548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003550 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
3553 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003554 else if (!strcmp(args[0], "load-server-state-from-file")) {
3555 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3556 err_code |= ERR_WARN;
3557 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3558 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3559 }
3560 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3561 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3562 }
3563 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3564 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3565 }
3566 else {
3567 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3568 file, linenum, args[0], args[1]);
3569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
3571 }
3572 }
3573 else if (!strcmp(args[0], "server-state-file-name")) {
3574 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3575 err_code |= ERR_WARN;
3576 if (*(args[1]) == 0) {
3577 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3578 file, linenum, args[0]);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
3581 }
3582 else if (!strcmp(args[1], "use-backend-name"))
3583 curproxy->server_state_file_name = strdup(curproxy->id);
3584 else
3585 curproxy->server_state_file_name = strdup(args[1]);
3586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003588 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003590
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003592 if (curproxy == &defproxy) {
3593 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597
William Lallemand1a748ae2015-05-19 16:37:23 +02003598 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3599 goto out;
3600
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 if (*(args[4]) == 0) {
3602 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003607 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 curproxy->capture_name = strdup(args[2]);
3609 curproxy->capture_namelen = strlen(curproxy->capture_name);
3610 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 curproxy->to_log |= LW_COOKIE;
3612 }
3613 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3614 struct cap_hdr *hdr;
3615
3616 if (curproxy == &defproxy) {
3617 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 +02003618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003620 }
3621
William Lallemand1a748ae2015-05-19 16:37:23 +02003622 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3623 goto out;
3624
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3626 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3627 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 }
3631
Vincent Bernat02779b62016-04-03 13:48:43 +02003632 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 hdr->next = curproxy->req_cap;
3634 hdr->name = strdup(args[3]);
3635 hdr->namelen = strlen(args[3]);
3636 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003637 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 hdr->index = curproxy->nb_req_cap++;
3639 curproxy->req_cap = hdr;
3640 curproxy->to_log |= LW_REQHDR;
3641 }
3642 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3643 struct cap_hdr *hdr;
3644
3645 if (curproxy == &defproxy) {
3646 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 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650
William Lallemand1a748ae2015-05-19 16:37:23 +02003651 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3652 goto out;
3653
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3655 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3656 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003660 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 hdr->next = curproxy->rsp_cap;
3662 hdr->name = strdup(args[3]);
3663 hdr->namelen = strlen(args[3]);
3664 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003665 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 hdr->index = curproxy->nb_rsp_cap++;
3667 curproxy->rsp_cap = hdr;
3668 curproxy->to_log |= LW_RSPHDR;
3669 }
3670 else {
3671 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3672 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 }
3676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003678 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003679 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003680
William Lallemanddf1425a2015-04-28 20:17:49 +02003681 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3682 goto out;
3683
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 if (*(args[1]) == 0) {
3685 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 }
3690 curproxy->conn_retries = atol(args[1]);
3691 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003692 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003693 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003694
3695 if (curproxy == &defproxy) {
3696 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700
Willy Tarreau20b0de52012-12-24 15:45:22 +01003701 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003702 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003703 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3704 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3705 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3706 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003707 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 +01003708 file, linenum, args[0]);
3709 err_code |= ERR_WARN;
3710 }
3711
Willy Tarreauff011f22011-01-06 17:51:27 +01003712 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003713
Willy Tarreauff011f22011-01-06 17:51:27 +01003714 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003715 err_code |= ERR_ALERT | ERR_ABORT;
3716 goto out;
3717 }
3718
Willy Tarreau5002f572014-04-23 01:32:02 +02003719 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003720 err_code |= warnif_cond_conflicts(rule->cond,
3721 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3722 file, linenum);
3723
Willy Tarreauff011f22011-01-06 17:51:27 +01003724 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003725 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003726 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003727 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003728
3729 if (curproxy == &defproxy) {
3730 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
3733 }
3734
3735 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003736 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003737 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3738 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003739 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3740 file, linenum, args[0]);
3741 err_code |= ERR_WARN;
3742 }
3743
3744 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3745
3746 if (!rule) {
3747 err_code |= ERR_ALERT | ERR_ABORT;
3748 goto out;
3749 }
3750
3751 err_code |= warnif_cond_conflicts(rule->cond,
3752 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3753 file, linenum);
3754
3755 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3756 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003757 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3758 /* set the header name and length into the proxy structure */
3759 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3760 err_code |= ERR_WARN;
3761
3762 if (!*args[1]) {
3763 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3764 file, linenum, args[0]);
3765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
3767 }
3768
3769 /* set the desired header name */
3770 free(curproxy->server_id_hdr_name);
3771 curproxy->server_id_hdr_name = strdup(args[1]);
3772 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3773 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003774 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003775 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003776
Willy Tarreaub099aca2008-10-12 17:26:37 +02003777 if (curproxy == &defproxy) {
3778 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003781 }
3782
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003783 /* emulate "block" using "http-request block". Since these rules are supposed to
3784 * be processed before all http-request rules, we put them into their own list
3785 * and will insert them at the end.
3786 */
3787 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3788 if (!rule) {
3789 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003790 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003791 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003792 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3793 err_code |= warnif_cond_conflicts(rule->cond,
3794 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3795 file, linenum);
3796 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003797
3798 if (!already_warned(WARN_BLOCK_DEPRECATED))
3799 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]);
3800
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003801 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003802 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003803 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003804
Cyril Bonté99ed3272010-01-24 23:29:44 +01003805 if (curproxy == &defproxy) {
3806 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
3810
Willy Tarreaube4653b2015-05-28 15:26:58 +02003811 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003812 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3813 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003816 }
3817
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003818 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003819 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003820 err_code |= warnif_cond_conflicts(rule->cond,
3821 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3822 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003823 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003824 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003825 struct switching_rule *rule;
3826
Willy Tarreaub099aca2008-10-12 17:26:37 +02003827 if (curproxy == &defproxy) {
3828 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003831 }
3832
Willy Tarreau55ea7572007-06-17 19:56:27 +02003833 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003835
3836 if (*(args[1]) == 0) {
3837 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003840 }
3841
Willy Tarreauf51658d2014-04-23 01:21:56 +02003842 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3843 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3844 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3845 file, linenum, errmsg);
3846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003849
Willy Tarreauf51658d2014-04-23 01:21:56 +02003850 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003851 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003852 else if (*args[2]) {
3853 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3854 file, linenum, args[2]);
3855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003858
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003859 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003860 if (!rule) {
3861 Alert("Out of memory error.\n");
3862 goto out;
3863 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003864 rule->cond = cond;
3865 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003866 rule->line = linenum;
3867 rule->file = strdup(file);
3868 if (!rule->file) {
3869 Alert("Out of memory error.\n");
3870 goto out;
3871 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003872 LIST_INIT(&rule->list);
3873 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3874 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003875 else if (strcmp(args[0], "use-server") == 0) {
3876 struct server_rule *rule;
3877
3878 if (curproxy == &defproxy) {
3879 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883
3884 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3885 err_code |= ERR_WARN;
3886
3887 if (*(args[1]) == 0) {
3888 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
3891 }
3892
3893 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3894 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3895 file, linenum, args[0]);
3896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
3898 }
3899
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003900 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3901 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3902 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003907 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003908
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003909 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003910 rule->cond = cond;
3911 rule->srv.name = strdup(args[1]);
3912 LIST_INIT(&rule->list);
3913 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3914 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3915 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003916 else if ((!strcmp(args[0], "force-persist")) ||
3917 (!strcmp(args[0], "ignore-persist"))) {
3918 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003919
3920 if (curproxy == &defproxy) {
3921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
3924 }
3925
3926 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3927 err_code |= ERR_WARN;
3928
Willy Tarreauef6494c2010-01-28 17:12:36 +01003929 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003930 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3931 file, linenum, args[0]);
3932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
3934 }
3935
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003936 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3937 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3938 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
3941 }
3942
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003943 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3944 * where force-persist is applied.
3945 */
3946 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003947
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003948 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003949 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003950 if (!strcmp(args[0], "force-persist")) {
3951 rule->type = PERSIST_TYPE_FORCE;
3952 } else {
3953 rule->type = PERSIST_TYPE_IGNORE;
3954 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003955 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003956 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003957 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003958 else if (!strcmp(args[0], "stick-table")) {
3959 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003960 struct proxy *other;
3961
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003962 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003963 if (other) {
3964 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3965 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003969
Emeric Brun32da3c42010-09-23 18:39:19 +02003970 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003971 curproxy->table.type = (unsigned int)-1;
3972 while (*args[myidx]) {
3973 const char *err;
3974
3975 if (strcmp(args[myidx], "size") == 0) {
3976 myidx++;
3977 if (!*(args[myidx])) {
3978 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3979 file, linenum, args[myidx-1]);
3980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
3982 }
3983 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3984 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3985 file, linenum, *err, args[myidx-1]);
3986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
3988 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003989 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003990 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003991 else if (strcmp(args[myidx], "peers") == 0) {
3992 myidx++;
Godbach50523162013-12-11 19:48:57 +08003993 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003994 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3995 file, linenum, args[myidx-1]);
3996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Godbach50523162013-12-11 19:48:57 +08003998 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003999 curproxy->table.peers.name = strdup(args[myidx++]);
4000 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004001 else if (strcmp(args[myidx], "expire") == 0) {
4002 myidx++;
4003 if (!*(args[myidx])) {
4004 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4005 file, linenum, args[myidx-1]);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
4009 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4010 if (err) {
4011 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4012 file, linenum, *err, args[myidx-1]);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004016 if (val > INT_MAX) {
4017 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4018 file, linenum, val);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004022 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004023 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004024 }
4025 else if (strcmp(args[myidx], "nopurge") == 0) {
4026 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004027 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004028 }
4029 else if (strcmp(args[myidx], "type") == 0) {
4030 myidx++;
4031 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4032 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4033 file, linenum, args[myidx]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004037 /* myidx already points to next arg */
4038 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004039 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004040 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004041 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004042
4043 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004044 nw = args[myidx];
4045 while (*nw) {
4046 /* the "store" keyword supports a comma-separated list */
4047 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004048 sa = NULL; /* store arg */
4049 while (*nw && *nw != ',') {
4050 if (*nw == '(') {
4051 *nw = 0;
4052 sa = ++nw;
4053 while (*nw != ')') {
4054 if (!*nw) {
4055 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4056 file, linenum, args[0], cw);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
4060 nw++;
4061 }
4062 *nw = '\0';
4063 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004064 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004065 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004066 if (*nw)
4067 *nw++ = '\0';
4068 type = stktable_get_data_type(cw);
4069 if (type < 0) {
4070 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4071 file, linenum, args[0], cw);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
Willy Tarreauac782882010-06-20 10:41:54 +02004075
4076 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4077 switch (err) {
4078 case PE_NONE: break;
4079 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004080 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4081 file, linenum, args[0], cw);
4082 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004083 break;
4084
4085 case PE_ARG_MISSING:
4086 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4087 file, linenum, args[0], cw);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090
4091 case PE_ARG_NOT_USED:
4092 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4093 file, linenum, args[0], cw);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096
4097 default:
4098 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4099 file, linenum, args[0], cw);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004102 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004103 }
4104 myidx++;
4105 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004106 else {
4107 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4108 file, linenum, args[myidx]);
4109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004111 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004112 }
4113
4114 if (!curproxy->table.size) {
4115 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4116 file, linenum);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120
4121 if (curproxy->table.type == (unsigned int)-1) {
4122 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4123 file, linenum);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127 }
4128 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004129 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004130 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 int myidx = 0;
4132 const char *name = NULL;
4133 int flags;
4134
4135 if (curproxy == &defproxy) {
4136 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
4139 }
4140
4141 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4142 err_code |= ERR_WARN;
4143 goto out;
4144 }
4145
4146 myidx++;
4147 if ((strcmp(args[myidx], "store") == 0) ||
4148 (strcmp(args[myidx], "store-request") == 0)) {
4149 myidx++;
4150 flags = STK_IS_STORE;
4151 }
4152 else if (strcmp(args[myidx], "store-response") == 0) {
4153 myidx++;
4154 flags = STK_IS_STORE | STK_ON_RSP;
4155 }
4156 else if (strcmp(args[myidx], "match") == 0) {
4157 myidx++;
4158 flags = STK_IS_MATCH;
4159 }
4160 else if (strcmp(args[myidx], "on") == 0) {
4161 myidx++;
4162 flags = STK_IS_MATCH | STK_IS_STORE;
4163 }
4164 else {
4165 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
4169
4170 if (*(args[myidx]) == 0) {
4171 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
4174 }
4175
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004176 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004177 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004178 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004179 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
4182 }
4183
4184 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004185 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4186 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4187 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004188 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004189 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004190 goto out;
4191 }
4192 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004193 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4194 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4195 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004196 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004197 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004198 goto out;
4199 }
4200 }
4201
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004202 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004203 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004204
Emeric Brunb982a3d2010-01-04 15:45:53 +01004205 if (strcmp(args[myidx], "table") == 0) {
4206 myidx++;
4207 name = args[myidx++];
4208 }
4209
Willy Tarreauef6494c2010-01-28 17:12:36 +01004210 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004211 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4212 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4213 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004214 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004215 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004216 goto out;
4217 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004218 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004219 else if (*(args[myidx])) {
4220 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4221 file, linenum, args[0], args[myidx]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004223 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004224 goto out;
4225 }
Emeric Brun97679e72010-09-23 17:56:44 +02004226 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004227 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004228 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004229 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004230
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004231 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004232 rule->cond = cond;
4233 rule->expr = expr;
4234 rule->flags = flags;
4235 rule->table.name = name ? strdup(name) : NULL;
4236 LIST_INIT(&rule->list);
4237 if (flags & STK_ON_RSP)
4238 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4239 else
4240 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 else if (!strcmp(args[0], "stats")) {
4243 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4244 curproxy->uri_auth = NULL; /* we must detach from the default config */
4245
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004246 if (!*args[1]) {
4247 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004248 } else if (!strcmp(args[1], "admin")) {
4249 struct stats_admin_rule *rule;
4250
4251 if (curproxy == &defproxy) {
4252 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 }
4256
4257 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4258 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4259 err_code |= ERR_ALERT | ERR_ABORT;
4260 goto out;
4261 }
4262
4263 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4264 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4265 file, linenum, args[0], args[1]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004269 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4270 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4271 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004276 err_code |= warnif_cond_conflicts(cond,
4277 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4278 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004279
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004280 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004281 rule->cond = cond;
4282 LIST_INIT(&rule->list);
4283 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 } else if (!strcmp(args[1], "uri")) {
4285 if (*(args[2]) == 0) {
4286 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4290 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_ABORT;
4292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 }
4294 } else if (!strcmp(args[1], "realm")) {
4295 if (*(args[2]) == 0) {
4296 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004299 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4300 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_ABORT;
4302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004304 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004305 unsigned interval;
4306
4307 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4308 if (err) {
4309 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4310 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004313 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_ABORT;
4316 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004317 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004318 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004319 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004320
4321 if (curproxy == &defproxy) {
4322 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
4325 }
4326
4327 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4328 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4329 err_code |= ERR_ALERT | ERR_ABORT;
4330 goto out;
4331 }
4332
Willy Tarreauff011f22011-01-06 17:51:27 +01004333 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004334 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004335 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4336 file, linenum, args[0]);
4337 err_code |= ERR_WARN;
4338 }
4339
Willy Tarreauff011f22011-01-06 17:51:27 +01004340 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004341
Willy Tarreauff011f22011-01-06 17:51:27 +01004342 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004343 err_code |= ERR_ALERT | ERR_ABORT;
4344 goto out;
4345 }
4346
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004347 err_code |= warnif_cond_conflicts(rule->cond,
4348 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4349 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004350 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004351
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 } else if (!strcmp(args[1], "auth")) {
4353 if (*(args[2]) == 0) {
4354 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004357 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4358 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004359 err_code |= ERR_ALERT | ERR_ABORT;
4360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 }
4362 } else if (!strcmp(args[1], "scope")) {
4363 if (*(args[2]) == 0) {
4364 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4368 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_ALERT | ERR_ABORT;
4370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 }
4372 } else if (!strcmp(args[1], "enable")) {
4373 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4374 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004375 err_code |= ERR_ALERT | ERR_ABORT;
4376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004378 } else if (!strcmp(args[1], "hide-version")) {
4379 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4380 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_ABORT;
4382 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004383 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004384 } else if (!strcmp(args[1], "show-legends")) {
4385 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4386 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4387 err_code |= ERR_ALERT | ERR_ABORT;
4388 goto out;
4389 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004390 } else if (!strcmp(args[1], "show-node")) {
4391
4392 if (*args[2]) {
4393 int i;
4394 char c;
4395
4396 for (i=0; args[2][i]; i++) {
4397 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004398 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4399 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004400 break;
4401 }
4402
4403 if (!i || args[2][i]) {
4404 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4405 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4406 file, linenum, args[0], args[1]);
4407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
4409 }
4410 }
4411
4412 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4413 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4414 err_code |= ERR_ALERT | ERR_ABORT;
4415 goto out;
4416 }
4417 } else if (!strcmp(args[1], "show-desc")) {
4418 char *desc = NULL;
4419
4420 if (*args[2]) {
4421 int i, len=0;
4422 char *d;
4423
Willy Tarreau348acfe2014-04-14 15:00:39 +02004424 for (i = 2; *args[i]; i++)
4425 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004426
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004427 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004428
Willy Tarreau348acfe2014-04-14 15:00:39 +02004429 d += snprintf(d, desc + len - d, "%s", args[2]);
4430 for (i = 3; *args[i]; i++)
4431 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004432 }
4433
4434 if (!*args[2] && !global.desc)
4435 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4436 file, linenum, args[1]);
4437 else {
4438 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4439 free(desc);
4440 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4441 err_code |= ERR_ALERT | ERR_ABORT;
4442 goto out;
4443 }
4444 free(desc);
4445 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004447stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004448 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 +01004449 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004452 }
4453 }
4454 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004455 int optnum;
4456
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004457 if (*(args[1]) == '\0') {
4458 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4459 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004463
4464 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4465 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004466 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4467 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4468 file, linenum, cfg_opts[optnum].name);
4469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
4471 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004472 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4473 goto out;
4474
Willy Tarreau93893792009-07-23 13:19:11 +02004475 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4476 err_code |= ERR_WARN;
4477 goto out;
4478 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004479
Willy Tarreau3842f002009-06-14 11:39:52 +02004480 curproxy->no_options &= ~cfg_opts[optnum].val;
4481 curproxy->options &= ~cfg_opts[optnum].val;
4482
4483 switch (kwm) {
4484 case KWM_STD:
4485 curproxy->options |= cfg_opts[optnum].val;
4486 break;
4487 case KWM_NO:
4488 curproxy->no_options |= cfg_opts[optnum].val;
4489 break;
4490 case KWM_DEF: /* already cleared */
4491 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004492 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004493
Willy Tarreau93893792009-07-23 13:19:11 +02004494 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004495 }
4496 }
4497
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004498 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4499 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004500 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4501 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4502 file, linenum, cfg_opts2[optnum].name);
4503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
4505 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004506 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4507 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004508 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4509 err_code |= ERR_WARN;
4510 goto out;
4511 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004512
Willy Tarreau3842f002009-06-14 11:39:52 +02004513 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4514 curproxy->options2 &= ~cfg_opts2[optnum].val;
4515
4516 switch (kwm) {
4517 case KWM_STD:
4518 curproxy->options2 |= cfg_opts2[optnum].val;
4519 break;
4520 case KWM_NO:
4521 curproxy->no_options2 |= cfg_opts2[optnum].val;
4522 break;
4523 case KWM_DEF: /* already cleared */
4524 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004525 }
Willy Tarreau93893792009-07-23 13:19:11 +02004526 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004527 }
4528 }
4529
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004530 /* HTTP options override each other. They can be cancelled using
4531 * "no option xxx" which only switches to default mode if the mode
4532 * was this one (useful for cancelling options set in defaults
4533 * sections).
4534 */
4535 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004536 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4537 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004538 if (kwm == KWM_STD) {
4539 curproxy->options &= ~PR_O_HTTP_MODE;
4540 curproxy->options |= PR_O_HTTP_PCL;
4541 goto out;
4542 }
4543 else if (kwm == KWM_NO) {
4544 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4545 curproxy->options &= ~PR_O_HTTP_MODE;
4546 goto out;
4547 }
4548 }
4549 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004550 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4551 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004552 if (kwm == KWM_STD) {
4553 curproxy->options &= ~PR_O_HTTP_MODE;
4554 curproxy->options |= PR_O_HTTP_FCL;
4555 goto out;
4556 }
4557 else if (kwm == KWM_NO) {
4558 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4559 curproxy->options &= ~PR_O_HTTP_MODE;
4560 goto out;
4561 }
4562 }
4563 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004564 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4565 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004566 if (kwm == KWM_STD) {
4567 curproxy->options &= ~PR_O_HTTP_MODE;
4568 curproxy->options |= PR_O_HTTP_SCL;
4569 goto out;
4570 }
4571 else if (kwm == KWM_NO) {
4572 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4573 curproxy->options &= ~PR_O_HTTP_MODE;
4574 goto out;
4575 }
4576 }
4577 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004578 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4579 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004580 if (kwm == KWM_STD) {
4581 curproxy->options &= ~PR_O_HTTP_MODE;
4582 curproxy->options |= PR_O_HTTP_KAL;
4583 goto out;
4584 }
4585 else if (kwm == KWM_NO) {
4586 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4587 curproxy->options &= ~PR_O_HTTP_MODE;
4588 goto out;
4589 }
4590 }
4591 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004592 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4593 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004594 if (kwm == KWM_STD) {
4595 curproxy->options &= ~PR_O_HTTP_MODE;
4596 curproxy->options |= PR_O_HTTP_TUN;
4597 goto out;
4598 }
4599 else if (kwm == KWM_NO) {
4600 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4601 curproxy->options &= ~PR_O_HTTP_MODE;
4602 goto out;
4603 }
4604 }
4605
Joseph Lynch726ab712015-05-11 23:25:34 -07004606 /* Redispatch can take an integer argument that control when the
4607 * resispatch occurs. All values are relative to the retries option.
4608 * This can be cancelled using "no option xxx".
4609 */
4610 if (strcmp(args[1], "redispatch") == 0) {
4611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4612 err_code |= ERR_WARN;
4613 goto out;
4614 }
4615
4616 curproxy->no_options &= ~PR_O_REDISP;
4617 curproxy->options &= ~PR_O_REDISP;
4618
4619 switch (kwm) {
4620 case KWM_STD:
4621 curproxy->options |= PR_O_REDISP;
4622 curproxy->redispatch_after = -1;
4623 if(*args[2]) {
4624 curproxy->redispatch_after = atol(args[2]);
4625 }
4626 break;
4627 case KWM_NO:
4628 curproxy->no_options |= PR_O_REDISP;
4629 curproxy->redispatch_after = 0;
4630 break;
4631 case KWM_DEF: /* already cleared */
4632 break;
4633 }
4634 goto out;
4635 }
4636
Willy Tarreau3842f002009-06-14 11:39:52 +02004637 if (kwm != KWM_STD) {
4638 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004639 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004642 }
4643
Emeric Brun3a058f32009-06-30 18:26:00 +02004644 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004645 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004647 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004648 if (*(args[2]) != '\0') {
4649 if (!strcmp(args[2], "clf")) {
4650 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004651 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004652 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004653 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004656 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004657 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4658 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004659 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004660 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4661 char *oldlogformat = "log-format";
4662 char *clflogformat = "";
4663
4664 if (curproxy->conf.logformat_string == default_http_log_format)
4665 oldlogformat = "option httplog";
4666 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4667 oldlogformat = "option tcplog";
4668 else if (curproxy->conf.logformat_string == clf_http_log_format)
4669 oldlogformat = "option httplog clf";
4670 if (logformat == clf_http_log_format)
4671 clflogformat = " clf";
4672 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4673 file, linenum, clflogformat, oldlogformat);
4674 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004675 if (curproxy->conf.logformat_string != default_http_log_format &&
4676 curproxy->conf.logformat_string != default_tcp_log_format &&
4677 curproxy->conf.logformat_string != clf_http_log_format)
4678 free(curproxy->conf.logformat_string);
4679 curproxy->conf.logformat_string = logformat;
4680
4681 free(curproxy->conf.lfs_file);
4682 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4683 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004684 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004685 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004686 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4687 char *oldlogformat = "log-format";
4688
4689 if (curproxy->conf.logformat_string == default_http_log_format)
4690 oldlogformat = "option httplog";
4691 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4692 oldlogformat = "option tcplog";
4693 else if (curproxy->conf.logformat_string == clf_http_log_format)
4694 oldlogformat = "option httplog clf";
4695 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4696 file, linenum, oldlogformat);
4697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004699 if (curproxy->conf.logformat_string != default_http_log_format &&
4700 curproxy->conf.logformat_string != default_tcp_log_format &&
4701 curproxy->conf.logformat_string != clf_http_log_format)
4702 free(curproxy->conf.logformat_string);
4703 curproxy->conf.logformat_string = default_tcp_log_format;
4704
4705 free(curproxy->conf.lfs_file);
4706 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4707 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004708
4709 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4710 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004713 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004714 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004716
William Lallemanddf1425a2015-04-28 20:17:49 +02004717 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4718 goto out;
4719
Willy Tarreau13943ab2006-12-31 00:24:10 +01004720 if (curproxy->cap & PR_CAP_FE)
4721 curproxy->options |= PR_O_TCP_CLI_KA;
4722 if (curproxy->cap & PR_CAP_BE)
4723 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 }
4725 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_WARN;
4728
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004730 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004731 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004732 curproxy->options2 &= ~PR_O2_CHK_ANY;
4733 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734 if (!*args[2]) { /* no argument */
4735 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4736 curproxy->check_len = strlen(DEF_CHECK_REQ);
4737 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004738 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004739 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004741 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004743 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 if (*args[4])
4745 reqlen += strlen(args[4]);
4746 else
4747 reqlen += strlen("HTTP/1.0");
4748
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004749 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004751 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004753 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4754 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004755 }
4756 else if (!strcmp(args[1], "ssl-hello-chk")) {
4757 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004759 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004760
Willy Tarreaua534fea2008-08-03 12:19:50 +02004761 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004762 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004763 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004764 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004765
4766 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
Willy Tarreau23677902007-05-08 23:50:35 +02004769 else if (!strcmp(args[1], "smtpchk")) {
4770 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004771 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004772 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004773 curproxy->options2 &= ~PR_O2_CHK_ANY;
4774 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004775
4776 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4777 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4778 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4779 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4780 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4781 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004782 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004783 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4784 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4785 } else {
4786 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4787 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4788 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4789 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4790 }
4791 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004792 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4793 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004794 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004795 else if (!strcmp(args[1], "pgsql-check")) {
4796 /* use PostgreSQL request to check servers' health */
4797 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4798 err_code |= ERR_WARN;
4799
4800 free(curproxy->check_req);
4801 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004802 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004803 curproxy->options2 |= PR_O2_PGSQL_CHK;
4804
4805 if (*(args[2])) {
4806 int cur_arg = 2;
4807
4808 while (*(args[cur_arg])) {
4809 if (strcmp(args[cur_arg], "user") == 0) {
4810 char * packet;
4811 uint32_t packet_len;
4812 uint32_t pv;
4813
4814 /* suboption header - needs additional argument for it */
4815 if (*(args[cur_arg+1]) == 0) {
4816 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4817 file, linenum, args[0], args[1], args[cur_arg]);
4818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 }
4821
4822 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4823 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4824 pv = htonl(0x30000); /* protocol version 3.0 */
4825
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004826 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004827
4828 memcpy(packet + 4, &pv, 4);
4829
4830 /* copy "user" */
4831 memcpy(packet + 8, "user", 4);
4832
4833 /* copy username */
4834 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4835
4836 free(curproxy->check_req);
4837 curproxy->check_req = packet;
4838 curproxy->check_len = packet_len;
4839
4840 packet_len = htonl(packet_len);
4841 memcpy(packet, &packet_len, 4);
4842 cur_arg += 2;
4843 } else {
4844 /* unknown suboption - catchall */
4845 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4846 file, linenum, args[0], args[1]);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
4850 } /* end while loop */
4851 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004852 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4853 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004854 }
4855
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004856 else if (!strcmp(args[1], "redis-check")) {
4857 /* use REDIS PING request to check servers' health */
4858 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4859 err_code |= ERR_WARN;
4860
4861 free(curproxy->check_req);
4862 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004863 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004864 curproxy->options2 |= PR_O2_REDIS_CHK;
4865
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004866 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004867 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4868 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004869
4870 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4871 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004872 }
4873
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004874 else if (!strcmp(args[1], "mysql-check")) {
4875 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4877 err_code |= ERR_WARN;
4878
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004879 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004880 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004881 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004882 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004883
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004884 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004885 * const char mysql40_client_auth_pkt[] = {
4886 * "\x0e\x00\x00" // packet length
4887 * "\x01" // packet number
4888 * "\x00\x00" // client capabilities
4889 * "\x00\x00\x01" // max packet
4890 * "haproxy\x00" // username (null terminated string)
4891 * "\x00" // filler (always 0x00)
4892 * "\x01\x00\x00" // packet length
4893 * "\x00" // packet number
4894 * "\x01" // COM_QUIT command
4895 * };
4896 */
4897
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004898 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4899 * const char mysql41_client_auth_pkt[] = {
4900 * "\x0e\x00\x00\" // packet length
4901 * "\x01" // packet number
4902 * "\x00\x00\x00\x00" // client capabilities
4903 * "\x00\x00\x00\x01" // max packet
4904 * "\x21" // character set (UTF-8)
4905 * char[23] // All zeroes
4906 * "haproxy\x00" // username (null terminated string)
4907 * "\x00" // filler (always 0x00)
4908 * "\x01\x00\x00" // packet length
4909 * "\x00" // packet number
4910 * "\x01" // COM_QUIT command
4911 * };
4912 */
4913
4914
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004915 if (*(args[2])) {
4916 int cur_arg = 2;
4917
4918 while (*(args[cur_arg])) {
4919 if (strcmp(args[cur_arg], "user") == 0) {
4920 char *mysqluser;
4921 int packetlen, reqlen, userlen;
4922
4923 /* suboption header - needs additional argument for it */
4924 if (*(args[cur_arg+1]) == 0) {
4925 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4926 file, linenum, args[0], args[1], args[cur_arg]);
4927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
4929 }
4930 mysqluser = args[cur_arg + 1];
4931 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004932
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004933 if (*(args[cur_arg+2])) {
4934 if (!strcmp(args[cur_arg+2], "post-41")) {
4935 packetlen = userlen + 7 + 27;
4936 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004937
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004938 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004939 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004940 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004941
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004942 snprintf(curproxy->check_req, 4, "%c%c%c",
4943 ((unsigned char) packetlen & 0xff),
4944 ((unsigned char) (packetlen >> 8) & 0xff),
4945 ((unsigned char) (packetlen >> 16) & 0xff));
4946
4947 curproxy->check_req[3] = 1;
4948 curproxy->check_req[5] = 130;
4949 curproxy->check_req[11] = 1;
4950 curproxy->check_req[12] = 33;
4951 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4952 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4953 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4954 cur_arg += 3;
4955 } else {
4956 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
4959 }
4960 } else {
4961 packetlen = userlen + 7;
4962 reqlen = packetlen + 9;
4963
4964 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004965 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004966 curproxy->check_len = reqlen;
4967
4968 snprintf(curproxy->check_req, 4, "%c%c%c",
4969 ((unsigned char) packetlen & 0xff),
4970 ((unsigned char) (packetlen >> 8) & 0xff),
4971 ((unsigned char) (packetlen >> 16) & 0xff));
4972
4973 curproxy->check_req[3] = 1;
4974 curproxy->check_req[5] = 128;
4975 curproxy->check_req[8] = 1;
4976 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4977 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4978 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4979 cur_arg += 2;
4980 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004981 } else {
4982 /* unknown suboption - catchall */
4983 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4984 file, linenum, args[0], args[1]);
4985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988 } /* end while loop */
4989 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004990 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004991 else if (!strcmp(args[1], "ldap-check")) {
4992 /* use LDAP request to check servers' health */
4993 free(curproxy->check_req);
4994 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004995 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004996 curproxy->options2 |= PR_O2_LDAP_CHK;
4997
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004998 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004999 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5000 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005001 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5002 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005003 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005004 else if (!strcmp(args[1], "spop-check")) {
5005 if (curproxy == &defproxy) {
5006 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5007 file, linenum, args[0], args[1]);
5008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010 }
5011 if (curproxy->cap & PR_CAP_FE) {
5012 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5013 file, linenum, args[0], args[1]);
5014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
5016 }
5017
5018 /* use SPOE request to check servers' health */
5019 free(curproxy->check_req);
5020 curproxy->check_req = NULL;
5021 curproxy->options2 &= ~PR_O2_CHK_ANY;
5022 curproxy->options2 |= PR_O2_SPOP_CHK;
5023
Christopher Faulet8ef75252017-02-20 22:56:03 +01005024 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005025 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
5028 }
5029 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5030 goto out;
5031 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005032 else if (!strcmp(args[1], "tcp-check")) {
5033 /* use raw TCPCHK send/expect to check servers' health */
5034 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5035 err_code |= ERR_WARN;
5036
5037 free(curproxy->check_req);
5038 curproxy->check_req = NULL;
5039 curproxy->options2 &= ~PR_O2_CHK_ANY;
5040 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005041 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5042 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005043 }
Simon Horman98637e52014-06-20 12:30:16 +09005044 else if (!strcmp(args[1], "external-check")) {
5045 /* excute an external command to check servers' health */
5046 free(curproxy->check_req);
5047 curproxy->check_req = NULL;
5048 curproxy->options2 &= ~PR_O2_CHK_ANY;
5049 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005050 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5051 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005052 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005053 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005054 int cur_arg;
5055
5056 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5057 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005058 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005059
Willy Tarreau87cf5142011-08-19 22:57:24 +02005060 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005061
5062 free(curproxy->fwdfor_hdr_name);
5063 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5064 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5065
5066 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5067 cur_arg = 2;
5068 while (*(args[cur_arg])) {
5069 if (!strcmp(args[cur_arg], "except")) {
5070 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005071 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005072 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5073 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005076 }
5077 /* flush useless bits */
5078 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005079 cur_arg += 2;
5080 } else if (!strcmp(args[cur_arg], "header")) {
5081 /* suboption header - needs additional argument for it */
5082 if (*(args[cur_arg+1]) == 0) {
5083 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5084 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005087 }
5088 free(curproxy->fwdfor_hdr_name);
5089 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5090 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5091 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005092 } else if (!strcmp(args[cur_arg], "if-none")) {
5093 curproxy->options &= ~PR_O_FF_ALWAYS;
5094 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005095 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005096 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005097 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005098 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005101 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005102 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005103 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005104 else if (!strcmp(args[1], "originalto")) {
5105 int cur_arg;
5106
5107 /* insert x-original-to field, but not for the IP address listed as an except.
5108 * set default options (ie: bitfield, header name, etc)
5109 */
5110
5111 curproxy->options |= PR_O_ORGTO;
5112
5113 free(curproxy->orgto_hdr_name);
5114 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5115 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5116
Willy Tarreau87cf5142011-08-19 22:57:24 +02005117 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005118 cur_arg = 2;
5119 while (*(args[cur_arg])) {
5120 if (!strcmp(args[cur_arg], "except")) {
5121 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005122 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 +02005123 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5124 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005127 }
5128 /* flush useless bits */
5129 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5130 cur_arg += 2;
5131 } else if (!strcmp(args[cur_arg], "header")) {
5132 /* suboption header - needs additional argument for it */
5133 if (*(args[cur_arg+1]) == 0) {
5134 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5135 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005138 }
5139 free(curproxy->orgto_hdr_name);
5140 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5141 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5142 cur_arg += 2;
5143 } else {
5144 /* unknown suboption - catchall */
5145 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5146 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005149 }
5150 } /* end while loop */
5151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 else {
5153 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreau93893792009-07-23 13:19:11 +02005157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005159 else if (!strcmp(args[0], "default_backend")) {
5160 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005161 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005162
5163 if (*(args[1]) == 0) {
5164 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005167 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005168 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005169 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005170
5171 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5172 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005175 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005177
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005178 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5179 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 +01005180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 /* enable reconnections to dispatch */
5183 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005184
5185 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005188 else if (!strcmp(args[0], "http-reuse")) {
5189 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5190 err_code |= ERR_WARN;
5191
5192 if (strcmp(args[1], "never") == 0) {
5193 /* enable a graceful server shutdown on an HTTP 404 response */
5194 curproxy->options &= ~PR_O_REUSE_MASK;
5195 curproxy->options |= PR_O_REUSE_NEVR;
5196 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5197 goto out;
5198 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005199 else if (strcmp(args[1], "safe") == 0) {
5200 /* enable a graceful server shutdown on an HTTP 404 response */
5201 curproxy->options &= ~PR_O_REUSE_MASK;
5202 curproxy->options |= PR_O_REUSE_SAFE;
5203 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5204 goto out;
5205 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005206 else if (strcmp(args[1], "aggressive") == 0) {
5207 curproxy->options &= ~PR_O_REUSE_MASK;
5208 curproxy->options |= PR_O_REUSE_AGGR;
5209 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5210 goto out;
5211 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005212 else if (strcmp(args[1], "always") == 0) {
5213 /* enable a graceful server shutdown on an HTTP 404 response */
5214 curproxy->options &= ~PR_O_REUSE_MASK;
5215 curproxy->options |= PR_O_REUSE_ALWS;
5216 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5217 goto out;
5218 }
5219 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005220 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
5224 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005225 else if (!strcmp(args[0], "http-check")) {
5226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005228
5229 if (strcmp(args[1], "disable-on-404") == 0) {
5230 /* enable a graceful server shutdown on an HTTP 404 response */
5231 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005232 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5233 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005234 }
Willy Tarreauef781042010-01-27 11:53:01 +01005235 else if (strcmp(args[1], "send-state") == 0) {
5236 /* enable emission of the apparent state of a server in HTTP checks */
5237 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005238 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5239 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005240 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005241 else if (strcmp(args[1], "expect") == 0) {
5242 const char *ptr_arg;
5243 int cur_arg;
5244
5245 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5246 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
5250
5251 cur_arg = 2;
5252 /* consider exclamation marks, sole or at the beginning of a word */
5253 while (*(ptr_arg = args[cur_arg])) {
5254 while (*ptr_arg == '!') {
5255 curproxy->options2 ^= PR_O2_EXP_INV;
5256 ptr_arg++;
5257 }
5258 if (*ptr_arg)
5259 break;
5260 cur_arg++;
5261 }
5262 /* now ptr_arg points to the beginning of a word past any possible
5263 * exclamation mark, and cur_arg is the argument which holds this word.
5264 */
5265 if (strcmp(ptr_arg, "status") == 0) {
5266 if (!*(args[cur_arg + 1])) {
5267 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5268 file, linenum, args[0], args[1], ptr_arg);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005273 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005274 curproxy->expect_str = strdup(args[cur_arg + 1]);
5275 }
5276 else if (strcmp(ptr_arg, "string") == 0) {
5277 if (!*(args[cur_arg + 1])) {
5278 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5279 file, linenum, args[0], args[1], ptr_arg);
5280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
5283 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005284 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005285 curproxy->expect_str = strdup(args[cur_arg + 1]);
5286 }
5287 else if (strcmp(ptr_arg, "rstatus") == 0) {
5288 if (!*(args[cur_arg + 1])) {
5289 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5290 file, linenum, args[0], args[1], ptr_arg);
5291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
5293 }
5294 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005295 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005296 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005297 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005298 free(curproxy->expect_regex);
5299 curproxy->expect_regex = NULL;
5300 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005301 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005302 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5303 error = NULL;
5304 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5305 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5306 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5307 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
5310 }
5311 }
5312 else if (strcmp(ptr_arg, "rstring") == 0) {
5313 if (!*(args[cur_arg + 1])) {
5314 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5315 file, linenum, args[0], args[1], ptr_arg);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
5319 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005320 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005321 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005322 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005323 free(curproxy->expect_regex);
5324 curproxy->expect_regex = NULL;
5325 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005326 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005327 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5328 error = NULL;
5329 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5330 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5331 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5332 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 }
5337 else {
5338 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5339 file, linenum, args[0], args[1], ptr_arg);
5340 err_code |= ERR_ALERT | ERR_FATAL;
5341 goto out;
5342 }
5343 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005344 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005345 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 +02005346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005348 }
5349 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005350 else if (!strcmp(args[0], "tcp-check")) {
5351 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5352 err_code |= ERR_WARN;
5353
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005354 if (strcmp(args[1], "comment") == 0) {
5355 int cur_arg;
5356 struct tcpcheck_rule *tcpcheck;
5357
5358 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005359 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005360 tcpcheck->action = TCPCHK_ACT_COMMENT;
5361
5362 if (!*args[cur_arg + 1]) {
5363 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5364 file, linenum, args[cur_arg]);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368
5369 tcpcheck->comment = strdup(args[cur_arg + 1]);
5370
5371 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005372 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5373 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005374 }
5375 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005376 const char *ptr_arg;
5377 int cur_arg;
5378 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005379
5380 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005381 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5382 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5383 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5384 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5385 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005386
Willy Tarreau5581c272015-05-13 12:24:53 +02005387 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5388 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5389 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5390 file, linenum);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005393 }
5394
5395 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005396 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005397 tcpcheck->action = TCPCHK_ACT_CONNECT;
5398
5399 /* parsing each parameters to fill up the rule */
5400 while (*(ptr_arg = args[cur_arg])) {
5401 /* tcp port */
5402 if (strcmp(args[cur_arg], "port") == 0) {
5403 if ( (atol(args[cur_arg + 1]) > 65535) ||
5404 (atol(args[cur_arg + 1]) < 1) ){
5405 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5406 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
5409 }
5410 tcpcheck->port = atol(args[cur_arg + 1]);
5411 cur_arg += 2;
5412 }
5413 /* send proxy protocol */
5414 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5415 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5416 cur_arg++;
5417 }
5418#ifdef USE_OPENSSL
5419 else if (strcmp(args[cur_arg], "ssl") == 0) {
5420 curproxy->options |= PR_O_TCPCHK_SSL;
5421 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5422 cur_arg++;
5423 }
5424#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005425 /* comment for this tcpcheck line */
5426 else if (strcmp(args[cur_arg], "comment") == 0) {
5427 if (!*args[cur_arg + 1]) {
5428 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5429 file, linenum, args[cur_arg]);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
5433 tcpcheck->comment = strdup(args[cur_arg + 1]);
5434 cur_arg += 2;
5435 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005436 else {
5437#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005438 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 +01005439#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005440 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 +01005441#endif /* USE_OPENSSL */
5442 file, linenum, args[0], args[1], args[cur_arg]);
5443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
5446
5447 }
5448
5449 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5450 }
5451 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005452 if (! *(args[2]) ) {
5453 /* SEND string expected */
5454 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5455 file, linenum, args[0], args[1], args[2]);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 } else {
5459 struct tcpcheck_rule *tcpcheck;
5460
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005461 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005462
5463 tcpcheck->action = TCPCHK_ACT_SEND;
5464 tcpcheck->string_len = strlen(args[2]);
5465 tcpcheck->string = strdup(args[2]);
5466 tcpcheck->expect_regex = NULL;
5467
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005468 /* comment for this tcpcheck line */
5469 if (strcmp(args[3], "comment") == 0) {
5470 if (!*args[4]) {
5471 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5472 file, linenum, args[3]);
5473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
5475 }
5476 tcpcheck->comment = strdup(args[4]);
5477 }
5478
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005479 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5480 }
5481 }
5482 else if (strcmp(args[1], "send-binary") == 0) {
5483 if (! *(args[2]) ) {
5484 /* SEND binary string expected */
5485 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5486 file, linenum, args[0], args[1], args[2]);
5487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
5489 } else {
5490 struct tcpcheck_rule *tcpcheck;
5491 char *err = NULL;
5492
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005493 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005494
5495 tcpcheck->action = TCPCHK_ACT_SEND;
5496 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5497 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5498 file, linenum, args[0], args[1], args[2], err);
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
5501 }
5502 tcpcheck->expect_regex = NULL;
5503
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005504 /* comment for this tcpcheck line */
5505 if (strcmp(args[3], "comment") == 0) {
5506 if (!*args[4]) {
5507 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5508 file, linenum, args[3]);
5509 err_code |= ERR_ALERT | ERR_FATAL;
5510 goto out;
5511 }
5512 tcpcheck->comment = strdup(args[4]);
5513 }
5514
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005515 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5516 }
5517 }
5518 else if (strcmp(args[1], "expect") == 0) {
5519 const char *ptr_arg;
5520 int cur_arg;
5521 int inverse = 0;
5522
5523 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5524 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528
5529 cur_arg = 2;
5530 /* consider exclamation marks, sole or at the beginning of a word */
5531 while (*(ptr_arg = args[cur_arg])) {
5532 while (*ptr_arg == '!') {
5533 inverse = !inverse;
5534 ptr_arg++;
5535 }
5536 if (*ptr_arg)
5537 break;
5538 cur_arg++;
5539 }
5540 /* now ptr_arg points to the beginning of a word past any possible
5541 * exclamation mark, and cur_arg is the argument which holds this word.
5542 */
5543 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005544 struct tcpcheck_rule *tcpcheck;
5545 char *err = NULL;
5546
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005547 if (!*(args[cur_arg + 1])) {
5548 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5549 file, linenum, args[0], args[1], ptr_arg);
5550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
5552 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005553
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005554 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005555
5556 tcpcheck->action = TCPCHK_ACT_EXPECT;
5557 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5558 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5559 file, linenum, args[0], args[1], args[2], err);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563 tcpcheck->expect_regex = NULL;
5564 tcpcheck->inverse = inverse;
5565
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005566 /* tcpcheck comment */
5567 cur_arg += 2;
5568 if (strcmp(args[cur_arg], "comment") == 0) {
5569 if (!*args[cur_arg + 1]) {
5570 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5571 file, linenum, args[cur_arg + 1]);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
5575 tcpcheck->comment = strdup(args[cur_arg + 1]);
5576 }
5577
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005578 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5579 }
5580 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005581 struct tcpcheck_rule *tcpcheck;
5582
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005583 if (!*(args[cur_arg + 1])) {
5584 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5585 file, linenum, args[0], args[1], ptr_arg);
5586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
5588 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005589
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005590 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005591
5592 tcpcheck->action = TCPCHK_ACT_EXPECT;
5593 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5594 tcpcheck->string = strdup(args[cur_arg + 1]);
5595 tcpcheck->expect_regex = NULL;
5596 tcpcheck->inverse = inverse;
5597
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005598 /* tcpcheck comment */
5599 cur_arg += 2;
5600 if (strcmp(args[cur_arg], "comment") == 0) {
5601 if (!*args[cur_arg + 1]) {
5602 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5603 file, linenum, args[cur_arg + 1]);
5604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 }
5607 tcpcheck->comment = strdup(args[cur_arg + 1]);
5608 }
5609
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005610 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5611 }
5612 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005613 struct tcpcheck_rule *tcpcheck;
5614
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005615 if (!*(args[cur_arg + 1])) {
5616 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5617 file, linenum, args[0], args[1], ptr_arg);
5618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005621
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005622 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005623
5624 tcpcheck->action = TCPCHK_ACT_EXPECT;
5625 tcpcheck->string_len = 0;
5626 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005627 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5628 error = NULL;
5629 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5630 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5631 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5632 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
5635 }
5636 tcpcheck->inverse = inverse;
5637
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005638 /* tcpcheck comment */
5639 cur_arg += 2;
5640 if (strcmp(args[cur_arg], "comment") == 0) {
5641 if (!*args[cur_arg + 1]) {
5642 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5643 file, linenum, args[cur_arg + 1]);
5644 err_code |= ERR_ALERT | ERR_FATAL;
5645 goto out;
5646 }
5647 tcpcheck->comment = strdup(args[cur_arg + 1]);
5648 }
5649
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005650 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5651 }
5652 else {
5653 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5654 file, linenum, args[0], args[1], ptr_arg);
5655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
5657 }
5658 }
5659 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005660 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
5663 }
5664 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005665 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005666 if (curproxy == &defproxy) {
5667 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005670 }
5671
Willy Tarreaub80c2302007-11-30 20:51:32 +01005672 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005674
5675 if (strcmp(args[1], "fail") == 0) {
5676 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005677 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005678 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5679 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005682 }
5683
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005684 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5685 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5686 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005689 }
5690 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5691 }
5692 else {
5693 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005694 err_code |= ERR_ALERT | ERR_FATAL;
5695 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005696 }
5697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698#ifdef TPROXY
5699 else if (!strcmp(args[0], "transparent")) {
5700 /* enable transparent proxy connections */
5701 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005702 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704 }
5705#endif
5706 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005707 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005708 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005709
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 if (*(args[1]) == 0) {
5711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 }
5715 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005716 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005719 else if (!strcmp(args[0], "backlog")) { /* backlog */
5720 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005722
5723 if (*(args[1]) == 0) {
5724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005727 }
5728 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5730 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005731 }
Willy Tarreau86034312006-12-29 00:10:33 +01005732 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005734 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005735
Willy Tarreau86034312006-12-29 00:10:33 +01005736 if (*(args[1]) == 0) {
5737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005740 }
5741 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5743 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5746 if (*(args[1]) == 0) {
5747 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005751 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5752 if (err) {
5753 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5754 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005757 }
5758 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 }
5762 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005763 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005764 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005765 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005766
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 if (curproxy == &defproxy) {
5768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005772 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005773 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005774
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005775 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005776 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005777 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005778 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005779 goto out;
5780 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005781
5782 proto = protocol_by_family(sk->ss_family);
5783 if (!proto || !proto->connect) {
5784 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5785 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
5789
5790 if (port1 != port2) {
5791 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5792 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005796
5797 if (!port1) {
5798 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5799 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
5802 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005803
William Lallemanddf1425a2015-04-28 20:17:49 +02005804 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5805 goto out;
5806
Willy Tarreaud5191e72010-02-09 20:50:45 +01005807 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005808 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 }
5810 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005812 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005813
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005814 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5815 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005820 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005821 /**
5822 * The syntax for hash-type config element is
5823 * hash-type {map-based|consistent} [[<algo>] avalanche]
5824 *
5825 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5826 */
5827 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005828
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5830 err_code |= ERR_WARN;
5831
5832 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005833 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5834 }
5835 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005836 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5837 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005838 else if (strcmp(args[1], "avalanche") == 0) {
5839 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]);
5840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005842 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005843 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005844 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005845 err_code |= ERR_ALERT | ERR_FATAL;
5846 goto out;
5847 }
Bhaskar98634f02013-10-29 23:30:51 -04005848
5849 /* set the hash function to use */
5850 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005851 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005852 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005853
5854 /* if consistent with no argument, then avalanche modifier is also applied */
5855 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5856 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005857 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005858 /* set the hash function */
5859 if (!strcmp(args[2], "sdbm")) {
5860 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5861 }
5862 else if (!strcmp(args[2], "djb2")) {
5863 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005864 }
5865 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005866 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005867 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005868 else if (!strcmp(args[2], "crc32")) {
5869 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5870 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005871 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005872 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 -05005873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
5875 }
5876
5877 /* set the hash modifier */
5878 if (!strcmp(args[3], "avalanche")) {
5879 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5880 }
5881 else if (*args[3]) {
5882 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
5885 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005886 }
William Lallemanda73203e2012-03-12 12:48:57 +01005887 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005888 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5889 if (*(args[1]) == 0) {
5890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
5893 }
5894 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5895 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5896 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
5900 }
William Lallemanda73203e2012-03-12 12:48:57 +01005901 else if (strcmp(args[0], "unique-id-format") == 0) {
5902 if (!*(args[1])) {
5903 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
William Lallemand3203ff42012-11-11 17:30:56 +01005907 if (*(args[2])) {
5908 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5909 err_code |= ERR_ALERT | ERR_FATAL;
5910 goto out;
5911 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005912 free(curproxy->conf.uniqueid_format_string);
5913 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005914
Willy Tarreau62a61232013-04-12 18:13:46 +02005915 free(curproxy->conf.uif_file);
5916 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5917 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005918 }
William Lallemanda73203e2012-03-12 12:48:57 +01005919
5920 else if (strcmp(args[0], "unique-id-header") == 0) {
5921 if (!*(args[1])) {
5922 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5923 err_code |= ERR_ALERT | ERR_FATAL;
5924 goto out;
5925 }
5926 free(curproxy->header_unique_id);
5927 curproxy->header_unique_id = strdup(args[1]);
5928 }
5929
William Lallemand723b73a2012-02-08 16:37:49 +01005930 else if (strcmp(args[0], "log-format") == 0) {
5931 if (!*(args[1])) {
5932 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
William Lallemand3203ff42012-11-11 17:30:56 +01005936 if (*(args[2])) {
5937 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
5940 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005941 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5942 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005943
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005944 if (curproxy->conf.logformat_string == default_http_log_format)
5945 oldlogformat = "option httplog";
5946 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5947 oldlogformat = "option tcplog";
5948 else if (curproxy->conf.logformat_string == clf_http_log_format)
5949 oldlogformat = "option httplog clf";
5950 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5951 file, linenum, oldlogformat);
5952 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005953 if (curproxy->conf.logformat_string != default_http_log_format &&
5954 curproxy->conf.logformat_string != default_tcp_log_format &&
5955 curproxy->conf.logformat_string != clf_http_log_format)
5956 free(curproxy->conf.logformat_string);
5957 curproxy->conf.logformat_string = strdup(args[1]);
5958
5959 free(curproxy->conf.lfs_file);
5960 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5961 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005962
5963 /* get a chance to improve log-format error reporting by
5964 * reporting the correct line-number when possible.
5965 */
5966 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5967 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5968 file, linenum, curproxy->id);
5969 err_code |= ERR_WARN;
5970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005972 else if (!strcmp(args[0], "log-format-sd")) {
5973 if (!*(args[1])) {
5974 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5975 err_code |= ERR_ALERT | ERR_FATAL;
5976 goto out;
5977 }
5978 if (*(args[2])) {
5979 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5980 err_code |= ERR_ALERT | ERR_FATAL;
5981 goto out;
5982 }
5983
5984 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5985 free(curproxy->conf.logformat_sd_string);
5986 curproxy->conf.logformat_sd_string = strdup(args[1]);
5987
5988 free(curproxy->conf.lfsd_file);
5989 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5990 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5991
5992 /* get a chance to improve log-format-sd error reporting by
5993 * reporting the correct line-number when possible.
5994 */
5995 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5996 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5997 file, linenum, curproxy->id);
5998 err_code |= ERR_WARN;
5999 }
6000 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006001 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6002 if (*(args[1]) == 0) {
6003 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
6006 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006007 chunk_destroy(&curproxy->log_tag);
6008 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006009 }
William Lallemand0f99e342011-10-12 17:50:54 +02006010 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6011 /* delete previous herited or defined syslog servers */
6012 struct logsrv *back;
6013
6014 if (*(args[1]) != 0) {
6015 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6016 err_code |= ERR_ALERT | ERR_FATAL;
6017 goto out;
6018 }
6019
William Lallemand723b73a2012-02-08 16:37:49 +01006020 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6021 LIST_DEL(&tmplogsrv->list);
6022 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006023 }
6024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006026 struct logsrv *logsrv;
6027
Willy Tarreaubaaee002006-06-26 02:48:02 +02006028 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006029 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006030 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006031 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006032 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006033 LIST_INIT(&node->list);
6034 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006036 }
6037 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006038 struct sockaddr_storage *sk;
6039 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006040 int arg = 0;
6041 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006042
Vincent Bernat02779b62016-04-03 13:48:43 +02006043 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044
Willy Tarreau18324f52014-06-27 18:10:07 +02006045 /* just after the address, a length may be specified */
6046 if (strcmp(args[arg+2], "len") == 0) {
6047 len = atoi(args[arg+3]);
6048 if (len < 80 || len > 65535) {
6049 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6050 file, linenum, args[arg+3]);
6051 err_code |= ERR_ALERT | ERR_FATAL;
6052 goto out;
6053 }
6054 logsrv->maxlen = len;
6055
6056 /* skip these two args */
6057 arg += 2;
6058 }
6059 else
6060 logsrv->maxlen = MAX_SYSLOG_LEN;
6061
Christopher Faulet084aa962017-08-29 16:54:41 +02006062 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006063 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006064
Dragan Dosen1322d092015-09-22 16:05:32 +02006065 /* after the length, a format may be specified */
6066 if (strcmp(args[arg+2], "format") == 0) {
6067 logsrv->format = get_log_format(args[arg+3]);
6068 if (logsrv->format < 0) {
6069 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6070 err_code |= ERR_ALERT | ERR_FATAL;
6071 goto out;
6072 }
6073
6074 /* skip these two args */
6075 arg += 2;
6076 }
6077
William Lallemanddf1425a2015-04-28 20:17:49 +02006078 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6079 goto out;
6080
Willy Tarreau18324f52014-06-27 18:10:07 +02006081 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006082 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006083 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006084 err_code |= ERR_ALERT | ERR_FATAL;
6085 goto out;
6086
Willy Tarreaubaaee002006-06-26 02:48:02 +02006087 }
6088
William Lallemand0f99e342011-10-12 17:50:54 +02006089 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006090 if (*(args[arg+3])) {
6091 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006092 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006093 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006094 err_code |= ERR_ALERT | ERR_FATAL;
6095 goto out;
6096
Willy Tarreaubaaee002006-06-26 02:48:02 +02006097 }
6098 }
6099
William Lallemand0f99e342011-10-12 17:50:54 +02006100 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006101 if (*(args[arg+4])) {
6102 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006103 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006104 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006105 err_code |= ERR_ALERT | ERR_FATAL;
6106 goto out;
6107
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006108 }
6109 }
6110
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006111 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006112 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006113 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006114 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006115 goto out;
6116 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006117
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006118 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006119
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006120 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006121 if (port1 != port2) {
6122 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6123 file, linenum, args[0], args[1]);
6124 err_code |= ERR_ALERT | ERR_FATAL;
6125 goto out;
6126 }
6127
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006128 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006129 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006130 }
William Lallemand0f99e342011-10-12 17:50:54 +02006131
6132 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006133 }
6134 else {
6135 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6136 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006137 err_code |= ERR_ALERT | ERR_FATAL;
6138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 }
6140 }
6141 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006142 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006143 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006144 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006145 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006146
Willy Tarreau977b8e42006-12-29 14:19:17 +01006147 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006148 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006149
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006151 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6152 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006156
6157 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006158 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6159 free(curproxy->conn_src.iface_name);
6160 curproxy->conn_src.iface_name = NULL;
6161 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006162
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006163 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006164 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006165 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006166 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006167 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006168 goto out;
6169 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006170
6171 proto = protocol_by_family(sk->ss_family);
6172 if (!proto || !proto->connect) {
6173 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006174 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006175 err_code |= ERR_ALERT | ERR_FATAL;
6176 goto out;
6177 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006178
6179 if (port1 != port2) {
6180 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6181 file, linenum, args[0], args[1]);
6182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
6184 }
6185
Willy Tarreauef9a3602012-12-08 22:29:20 +01006186 curproxy->conn_src.source_addr = *sk;
6187 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006188
6189 cur_arg = 2;
6190 while (*(args[cur_arg])) {
6191 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006192#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006193 if (!*args[cur_arg + 1]) {
6194 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6195 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006196 err_code |= ERR_ALERT | ERR_FATAL;
6197 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006198 }
6199
6200 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006201 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6202 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006203 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006204 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6205 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006206 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6207 char *name, *end;
6208
6209 name = args[cur_arg+1] + 7;
6210 while (isspace(*name))
6211 name++;
6212
6213 end = name;
6214 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6215 end++;
6216
Willy Tarreauef9a3602012-12-08 22:29:20 +01006217 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6218 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6219 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6220 curproxy->conn_src.bind_hdr_len = end - name;
6221 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6222 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6223 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006224
6225 /* now look for an occurrence number */
6226 while (isspace(*end))
6227 end++;
6228 if (*end == ',') {
6229 end++;
6230 name = end;
6231 if (*end == '-')
6232 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006233 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006234 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006235 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006236 }
6237
Willy Tarreauef9a3602012-12-08 22:29:20 +01006238 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006239 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6240 " occurrences values smaller than %d.\n",
6241 file, linenum, MAX_HDR_HISTORY);
6242 err_code |= ERR_ALERT | ERR_FATAL;
6243 goto out;
6244 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006245 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006246 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006247
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006248 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006249 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006250 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006251 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006252 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006253 goto out;
6254 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006255
6256 proto = protocol_by_family(sk->ss_family);
6257 if (!proto || !proto->connect) {
6258 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6259 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006260 err_code |= ERR_ALERT | ERR_FATAL;
6261 goto out;
6262 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006263
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006264 if (port1 != port2) {
6265 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6266 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006267 err_code |= ERR_ALERT | ERR_FATAL;
6268 goto out;
6269 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006270 curproxy->conn_src.tproxy_addr = *sk;
6271 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006272 }
6273 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006274#else /* no TPROXY support */
6275 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006276 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006277 err_code |= ERR_ALERT | ERR_FATAL;
6278 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006279#endif
6280 cur_arg += 2;
6281 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006282 }
6283
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006284 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6285#ifdef SO_BINDTODEVICE
6286 if (!*args[cur_arg + 1]) {
6287 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006289 err_code |= ERR_ALERT | ERR_FATAL;
6290 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006291 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006292 free(curproxy->conn_src.iface_name);
6293 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6294 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006295 global.last_checks |= LSTCHK_NETADM;
6296#else
6297 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6298 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006299 err_code |= ERR_ALERT | ERR_FATAL;
6300 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006301#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006302 cur_arg += 2;
6303 continue;
6304 }
6305 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006306 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006307 err_code |= ERR_ALERT | ERR_FATAL;
6308 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006310 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006311 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6312 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6313 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006317 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006321 err_code |= ERR_ALERT | ERR_FATAL;
6322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006324
6325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006326 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006327 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
6331 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006333 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006334 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
6338 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006340 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
6345 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006347 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006348 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006359 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006368 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006370 err_code |= ERR_ALERT | ERR_FATAL;
6371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006373
6374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006375 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006376 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
6380 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006382 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006383 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006384 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 }
6387 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006389 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006390 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006391 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 }
6394 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006396 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006397 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006398 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400 }
6401 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006403 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006404 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006405 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006408 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006410 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006411 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006412 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006413 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006416 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006417
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 if (curproxy == &defproxy) {
6419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006420 err_code |= ERR_ALERT | ERR_FATAL;
6421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006423 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006424 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 if (*(args[1]) == 0) {
6427 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006428 err_code |= ERR_ALERT | ERR_FATAL;
6429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006431
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006432 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006433 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6434 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6435 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006436 err_code |= ERR_ALERT | ERR_FATAL;
6437 goto out;
6438 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006439 err_code |= warnif_cond_conflicts(cond,
6440 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6441 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006442 }
6443 else if (*args[2]) {
6444 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6445 file, linenum, args[0], args[2]);
6446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto out;
6448 }
6449
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006450 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006451 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006452 wl->s = strdup(args[1]);
6453 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006454 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
6456 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6459 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006460 err_code |= ERR_ALERT | ERR_FATAL;
6461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006463
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006465 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006466 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006472 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006473 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
6477 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006479 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006480 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006481 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 }
6484 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006486 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6487 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006488 err_code |= ERR_ALERT | ERR_FATAL;
6489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 }
6491
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006493 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006494 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006495 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 }
6498 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006500 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006501 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006502 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 }
6505 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006507 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006508 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006509 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006513 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006514
Willy Tarreaubaaee002006-06-26 02:48:02 +02006515 if (curproxy == &defproxy) {
6516 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006517 err_code |= ERR_ALERT | ERR_FATAL;
6518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006520 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006521 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 if (*(args[1]) == 0) {
6524 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006525 err_code |= ERR_ALERT | ERR_FATAL;
6526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 }
6528
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006529 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006530 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6531 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6532 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006533 err_code |= ERR_ALERT | ERR_FATAL;
6534 goto out;
6535 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006536 err_code |= warnif_cond_conflicts(cond,
6537 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6538 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006539 }
6540 else if (*args[2]) {
6541 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6542 file, linenum, args[0], args[2]);
6543 err_code |= ERR_ALERT | ERR_FATAL;
6544 goto out;
6545 }
6546
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006547 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006548 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006549 wl->s = strdup(args[1]);
6550 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006551 }
6552 else if (!strcmp(args[0], "errorloc") ||
6553 !strcmp(args[0], "errorloc302") ||
6554 !strcmp(args[0], "errorloc303")) { /* error location */
6555 int errnum, errlen;
6556 char *err;
6557
Willy Tarreau977b8e42006-12-29 14:19:17 +01006558 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006559 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006560
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006562 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006563 err_code |= ERR_ALERT | ERR_FATAL;
6564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565 }
6566
6567 errnum = atol(args[1]);
6568 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006569 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6570 err = malloc(errlen);
6571 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006573 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6574 err = malloc(errlen);
6575 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006576 }
6577
Willy Tarreau0f772532006-12-23 20:51:41 +01006578 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6579 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006580 chunk_destroy(&curproxy->errmsg[rc]);
6581 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006582 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006585
6586 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006587 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6588 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589 free(err);
6590 }
6591 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006592 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6593 int errnum, errlen, fd;
6594 char *err;
6595 struct stat stat;
6596
6597 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006598 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006599
6600 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006601 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006602 err_code |= ERR_ALERT | ERR_FATAL;
6603 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006604 }
6605
6606 fd = open(args[2], O_RDONLY);
6607 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6608 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6609 file, linenum, args[2], args[1]);
6610 if (fd >= 0)
6611 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006612 err_code |= ERR_ALERT | ERR_FATAL;
6613 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006614 }
6615
Willy Tarreau27a674e2009-08-17 07:23:33 +02006616 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006617 errlen = stat.st_size;
6618 } else {
6619 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006620 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006621 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006622 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006623 }
6624
6625 err = malloc(errlen); /* malloc() must succeed during parsing */
6626 errnum = read(fd, err, errlen);
6627 if (errnum != errlen) {
6628 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6629 file, linenum, args[2], args[1]);
6630 close(fd);
6631 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006632 err_code |= ERR_ALERT | ERR_FATAL;
6633 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006634 }
6635 close(fd);
6636
6637 errnum = atol(args[1]);
6638 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6639 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006640 chunk_destroy(&curproxy->errmsg[rc]);
6641 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006642 break;
6643 }
6644 }
6645
6646 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006647 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6648 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006649 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006650 free(err);
6651 }
6652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006653 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006654 struct cfg_kw_list *kwl;
6655 int index;
6656
6657 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6658 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6659 if (kwl->kw[index].section != CFG_LISTEN)
6660 continue;
6661 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6662 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006663 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006664 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006665 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006666 err_code |= ERR_ALERT | ERR_FATAL;
6667 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006668 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006669 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006670 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006671 err_code |= ERR_WARN;
6672 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006673 }
Willy Tarreau93893792009-07-23 13:19:11 +02006674 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006675 }
6676 }
6677 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006678
Willy Tarreau6daf3432008-01-22 16:44:08 +01006679 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006680 err_code |= ERR_ALERT | ERR_FATAL;
6681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006682 }
Willy Tarreau93893792009-07-23 13:19:11 +02006683 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006684 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006685 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006686}
6687
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006688int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006689cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6690{
6691#ifdef CONFIG_HAP_NS
6692 const char *err;
6693 const char *item = args[0];
6694
6695 if (!strcmp(item, "namespace_list")) {
6696 return 0;
6697 }
6698 else if (!strcmp(item, "namespace")) {
6699 size_t idx = 1;
6700 const char *current;
6701 while (*(current = args[idx++])) {
6702 err = invalid_char(current);
6703 if (err) {
6704 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6705 file, linenum, *err, item, current);
6706 return ERR_ALERT | ERR_FATAL;
6707 }
6708
6709 if (netns_store_lookup(current, strlen(current))) {
6710 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6711 file, linenum, current);
6712 return ERR_ALERT | ERR_FATAL;
6713 }
6714 if (!netns_store_insert(current)) {
6715 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6716 file, linenum, current);
6717 return ERR_ALERT | ERR_FATAL;
6718 }
6719 }
6720 }
6721
6722 return 0;
6723#else
6724 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6725 file, linenum);
6726 return ERR_ALERT | ERR_FATAL;
6727#endif
6728}
6729
6730int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006731cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6732{
6733
6734 int err_code = 0;
6735 const char *err;
6736
6737 if (!strcmp(args[0], "userlist")) { /* new userlist */
6738 struct userlist *newul;
6739
6740 if (!*args[1]) {
6741 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6742 file, linenum, args[0]);
6743 err_code |= ERR_ALERT | ERR_FATAL;
6744 goto out;
6745 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006746 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6747 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006748
6749 err = invalid_char(args[1]);
6750 if (err) {
6751 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6752 file, linenum, *err, args[0], args[1]);
6753 err_code |= ERR_ALERT | ERR_FATAL;
6754 goto out;
6755 }
6756
6757 for (newul = userlist; newul; newul = newul->next)
6758 if (!strcmp(newul->name, args[1])) {
6759 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6760 file, linenum, args[1]);
6761 err_code |= ERR_WARN;
6762 goto out;
6763 }
6764
Vincent Bernat02779b62016-04-03 13:48:43 +02006765 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766 if (!newul) {
6767 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6768 err_code |= ERR_ALERT | ERR_ABORT;
6769 goto out;
6770 }
6771
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006772 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006773 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006774 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6775 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006776 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006777 goto out;
6778 }
6779
6780 newul->next = userlist;
6781 userlist = newul;
6782
6783 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006784 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006785 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006786 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006787
6788 if (!*args[1]) {
6789 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6790 file, linenum, args[0]);
6791 err_code |= ERR_ALERT | ERR_FATAL;
6792 goto out;
6793 }
6794
6795 err = invalid_char(args[1]);
6796 if (err) {
6797 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6798 file, linenum, *err, args[0], args[1]);
6799 err_code |= ERR_ALERT | ERR_FATAL;
6800 goto out;
6801 }
6802
William Lallemand4ac9f542015-05-28 18:03:51 +02006803 if (!userlist)
6804 goto out;
6805
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006806 for (ag = userlist->groups; ag; ag = ag->next)
6807 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006808 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6809 file, linenum, args[1], userlist->name);
6810 err_code |= ERR_ALERT;
6811 goto out;
6812 }
6813
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006814 ag = calloc(1, sizeof(*ag));
6815 if (!ag) {
6816 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6817 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006818 goto out;
6819 }
6820
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006821 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006822 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006823 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6824 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006825 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006826 goto out;
6827 }
6828
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006829 cur_arg = 2;
6830
6831 while (*args[cur_arg]) {
6832 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006833 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 cur_arg += 2;
6835 continue;
6836 } else {
6837 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6838 file, linenum, args[0]);
6839 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006840 free(ag->groupusers);
6841 free(ag->name);
6842 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006843 goto out;
6844 }
6845 }
6846
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006847 ag->next = userlist->groups;
6848 userlist->groups = ag;
6849
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006850 } else if (!strcmp(args[0], "user")) { /* new user */
6851 struct auth_users *newuser;
6852 int cur_arg;
6853
6854 if (!*args[1]) {
6855 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6856 file, linenum, args[0]);
6857 err_code |= ERR_ALERT | ERR_FATAL;
6858 goto out;
6859 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006860 if (!userlist)
6861 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006862
6863 for (newuser = userlist->users; newuser; newuser = newuser->next)
6864 if (!strcmp(newuser->user, args[1])) {
6865 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6866 file, linenum, args[1], userlist->name);
6867 err_code |= ERR_ALERT;
6868 goto out;
6869 }
6870
Vincent Bernat02779b62016-04-03 13:48:43 +02006871 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006872 if (!newuser) {
6873 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6874 err_code |= ERR_ALERT | ERR_ABORT;
6875 goto out;
6876 }
6877
6878 newuser->user = strdup(args[1]);
6879
6880 newuser->next = userlist->users;
6881 userlist->users = newuser;
6882
6883 cur_arg = 2;
6884
6885 while (*args[cur_arg]) {
6886 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006887#ifdef CONFIG_HAP_CRYPT
6888 if (!crypt("", args[cur_arg + 1])) {
6889 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6890 file, linenum, newuser->user);
6891 err_code |= ERR_ALERT | ERR_FATAL;
6892 goto out;
6893 }
6894#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006895 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6896 file, linenum);
6897 err_code |= ERR_ALERT;
6898#endif
6899 newuser->pass = strdup(args[cur_arg + 1]);
6900 cur_arg += 2;
6901 continue;
6902 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6903 newuser->pass = strdup(args[cur_arg + 1]);
6904 newuser->flags |= AU_O_INSECURE;
6905 cur_arg += 2;
6906 continue;
6907 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006908 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006909 cur_arg += 2;
6910 continue;
6911 } else {
6912 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6913 file, linenum, args[0]);
6914 err_code |= ERR_ALERT | ERR_FATAL;
6915 goto out;
6916 }
6917 }
6918 } else {
6919 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6920 err_code |= ERR_ALERT | ERR_FATAL;
6921 }
6922
6923out:
6924 return err_code;
6925}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926
Christopher Faulet79bdef32016-11-04 22:36:15 +01006927int
6928cfg_parse_scope(const char *file, int linenum, char *line)
6929{
6930 char *beg, *end, *scope = NULL;
6931 int err_code = 0;
6932 const char *err;
6933
6934 beg = line + 1;
6935 end = strchr(beg, ']');
6936
6937 /* Detect end of scope declaration */
6938 if (!end || end == beg) {
6939 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6940 file, linenum);
6941 err_code |= ERR_ALERT | ERR_FATAL;
6942 goto out;
6943 }
6944
6945 /* Get scope name and check its validity */
6946 scope = my_strndup(beg, end-beg);
6947 err = invalid_char(scope);
6948 if (err) {
6949 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6950 file, linenum, *err);
6951 err_code |= ERR_ALERT | ERR_ABORT;
6952 goto out;
6953 }
6954
6955 /* Be sure to have a scope declaration alone on its line */
6956 line = end+1;
6957 while (isspace((unsigned char)*line))
6958 line++;
6959 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6960 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6961 file, linenum, *line);
6962 err_code |= ERR_ALERT | ERR_ABORT;
6963 goto out;
6964 }
6965
6966 /* We have a valid scope declaration, save it */
6967 free(cfg_scope);
6968 cfg_scope = scope;
6969 scope = NULL;
6970
6971 out:
6972 free(scope);
6973 return err_code;
6974}
6975
Willy Tarreaubaaee002006-06-26 02:48:02 +02006976/*
6977 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006978 * Returns the error code, 0 if OK, or any combination of :
6979 * - ERR_ABORT: must abort ASAP
6980 * - ERR_FATAL: we can continue parsing but not start the service
6981 * - ERR_WARN: a warning has been emitted
6982 * - ERR_ALERT: an alert has been emitted
6983 * Only the two first ones can stop processing, the two others are just
6984 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006985 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006986int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006987{
William Lallemand64e84512015-05-12 14:25:37 +02006988 char *thisline;
6989 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006990 FILE *f;
6991 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006992 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02006993 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006994 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006995 int readbytes = 0;
6996
6997 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006998 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006999 return -1;
7000 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007001
David Carlier97880bb2016-04-08 10:35:26 +01007002 if ((f=fopen(file,"r")) == NULL) {
7003 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007004 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007006
William Lallemandb2f07452015-05-12 14:27:13 +02007007next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007008 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007009 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007010 char *end;
7011 char *args[MAX_LINE_ARGS + 1];
7012 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007013 int dquote = 0; /* double quote */
7014 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007015
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 linenum++;
7017
7018 end = line + strlen(line);
7019
William Lallemand64e84512015-05-12 14:25:37 +02007020 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007021 /* Check if we reached the limit and the last char is not \n.
7022 * Watch out for the last line without the terminating '\n'!
7023 */
William Lallemand64e84512015-05-12 14:25:37 +02007024 char *newline;
7025 int newlinesize = linesize * 2;
7026
7027 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7028 if (newline == NULL) {
7029 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7030 file, linenum);
7031 err_code |= ERR_ALERT | ERR_FATAL;
7032 continue;
7033 }
7034
7035 readbytes = linesize - 1;
7036 linesize = newlinesize;
7037 thisline = newline;
7038 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007039 }
7040
William Lallemand64e84512015-05-12 14:25:37 +02007041 readbytes = 0;
7042
Willy Tarreaubaaee002006-06-26 02:48:02 +02007043 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007044 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007045 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007046
Christopher Faulet79bdef32016-11-04 22:36:15 +01007047
7048 if (*line == '[') {/* This is the begining if a scope */
7049 err_code |= cfg_parse_scope(file, linenum, line);
7050 goto next_line;
7051 }
7052
Willy Tarreaubaaee002006-06-26 02:48:02 +02007053 arg = 0;
7054 args[arg] = line;
7055
7056 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007057 if (*line == '"' && !squote) { /* double quote outside single quotes */
7058 if (dquote)
7059 dquote = 0;
7060 else
7061 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007062 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007063 end--;
7064 }
7065 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7066 if (squote)
7067 squote = 0;
7068 else
7069 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007070 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007071 end--;
7072 }
7073 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007074 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7075 * C equivalent value. Other combinations left unchanged (eg: \1).
7076 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007077 int skip = 0;
7078 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7079 *line = line[1];
7080 skip = 1;
7081 }
7082 else if (line[1] == 'r') {
7083 *line = '\r';
7084 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007086 else if (line[1] == 'n') {
7087 *line = '\n';
7088 skip = 1;
7089 }
7090 else if (line[1] == 't') {
7091 *line = '\t';
7092 skip = 1;
7093 }
7094 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007095 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 unsigned char hex1, hex2;
7097 hex1 = toupper(line[2]) - '0';
7098 hex2 = toupper(line[3]) - '0';
7099 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7100 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7101 *line = (hex1<<4) + hex2;
7102 skip = 3;
7103 }
7104 else {
7105 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007106 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007107 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007108 } else if (line[1] == '"') {
7109 *line = '"';
7110 skip = 1;
7111 } else if (line[1] == '\'') {
7112 *line = '\'';
7113 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007114 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7115 *line = '$';
7116 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007117 }
7118 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007119 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007120 end -= skip;
7121 }
7122 line++;
7123 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007124 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007125 /* end of string, end of loop */
7126 *line = 0;
7127 break;
7128 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007129 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007130 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007131 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007132 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133 line++;
7134 args[++arg] = line;
7135 }
William Lallemandb2f07452015-05-12 14:27:13 +02007136 else if (dquote && *line == '$') {
7137 /* environment variables are evaluated inside double quotes */
7138 char *var_beg;
7139 char *var_end;
7140 char save_char;
7141 char *value;
7142 int val_len;
7143 int newlinesize;
7144 int braces = 0;
7145
7146 var_beg = line + 1;
7147 var_end = var_beg;
7148
7149 if (*var_beg == '{') {
7150 var_beg++;
7151 var_end++;
7152 braces = 1;
7153 }
7154
7155 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7156 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7157 err_code |= ERR_ALERT | ERR_FATAL;
7158 goto next_line; /* skip current line */
7159 }
7160
7161 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7162 var_end++;
7163
7164 save_char = *var_end;
7165 *var_end = '\0';
7166 value = getenv(var_beg);
7167 *var_end = save_char;
7168 val_len = value ? strlen(value) : 0;
7169
7170 if (braces) {
7171 if (*var_end == '}') {
7172 var_end++;
7173 braces = 0;
7174 } else {
7175 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7176 err_code |= ERR_ALERT | ERR_FATAL;
7177 goto next_line; /* skip current line */
7178 }
7179 }
7180
7181 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7182
7183 /* if not enough space in thisline */
7184 if (newlinesize > linesize) {
7185 char *newline;
7186
7187 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7188 if (newline == NULL) {
7189 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7190 err_code |= ERR_ALERT | ERR_FATAL;
7191 goto next_line; /* slip current line */
7192 }
7193 /* recompute pointers if realloc returns a new pointer */
7194 if (newline != thisline) {
7195 int i;
7196 int diff;
7197
7198 for (i = 0; i <= arg; i++) {
7199 diff = args[i] - thisline;
7200 args[i] = newline + diff;
7201 }
7202
7203 diff = var_end - thisline;
7204 var_end = newline + diff;
7205 diff = end - thisline;
7206 end = newline + diff;
7207 diff = line - thisline;
7208 line = newline + diff;
7209 thisline = newline;
7210 }
7211 linesize = newlinesize;
7212 }
7213
7214 /* insert value inside the line */
7215 memmove(line + val_len, var_end, end - var_end + 1);
7216 memcpy(line, value, val_len);
7217 end += val_len - (var_end - line);
7218 line += val_len;
7219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007220 else {
7221 line++;
7222 }
7223 }
William Lallemandb2f07452015-05-12 14:27:13 +02007224
William Lallemandf9873ba2015-05-05 17:37:14 +02007225 if (dquote) {
7226 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7227 err_code |= ERR_ALERT | ERR_FATAL;
7228 }
7229
7230 if (squote) {
7231 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7232 err_code |= ERR_ALERT | ERR_FATAL;
7233 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007234
7235 /* empty line */
7236 if (!**args)
7237 continue;
7238
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007239 if (*line) {
7240 /* we had to stop due to too many args.
7241 * Let's terminate the string, print the offending part then cut the
7242 * last arg.
7243 */
7244 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7245 line++;
7246 *line = '\0';
7247
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007248 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007249 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007250 err_code |= ERR_ALERT | ERR_FATAL;
7251 args[arg] = line;
7252 }
7253
Willy Tarreau540abe42007-05-02 20:50:16 +02007254 /* zero out remaining args and ensure that at least one entry
7255 * is zeroed out.
7256 */
7257 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007258 args[arg] = line;
7259 }
7260
Willy Tarreau3842f002009-06-14 11:39:52 +02007261 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007262 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007263 char *tmp;
7264
Willy Tarreau3842f002009-06-14 11:39:52 +02007265 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007266 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007267 for (arg=0; *args[arg+1]; arg++)
7268 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007269 *tmp = '\0'; // fix the next arg to \0
7270 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007271 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007272 else if (!strcmp(args[0], "default")) {
7273 kwm = KWM_DEF;
7274 for (arg=0; *args[arg+1]; arg++)
7275 args[arg] = args[arg+1]; // shift args after inversion
7276 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007277
William Lallemand0f99e342011-10-12 17:50:54 +02007278 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7279 strcmp(args[0], "log") != 0) {
7280 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007281 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007282 }
7283
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007284 /* detect section start */
7285 list_for_each_entry(ics, &sections, list) {
7286 if (strcmp(args[0], ics->section_name) == 0) {
7287 cursection = ics->section_name;
7288 cs = ics;
7289 break;
7290 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007291 }
7292
William Lallemandd2ff56d2017-10-16 11:06:50 +02007293 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007294 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007295 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007296 } else {
7297 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007298
William Lallemandd2ff56d2017-10-16 11:06:50 +02007299 if (pcs != cs && pcs && pcs->post_section_parser) {
7300 err_code |= pcs->post_section_parser();
7301 if (err_code & ERR_ABORT)
7302 goto err;
7303 }
7304
7305 err_code |= cs->section_parser(file, linenum, args, kwm);
7306 if (err_code & ERR_ABORT)
7307 goto err;
7308 }
7309 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007310 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007311
7312 if (pcs == cs && pcs && pcs->post_section_parser)
7313 err_code |= pcs->post_section_parser();
7314
7315err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007316 free(cfg_scope);
7317 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007318 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007319 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007320 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007321 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007322}
7323
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324/* This function propagates processes from frontend <from> to backend <to> so
7325 * that it is always guaranteed that a backend pointed to by a frontend is
7326 * bound to all of its processes. After that, if the target is a "listen"
7327 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007328 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007329 * checked first to ensure that <to> is already bound to all processes of
7330 * <from>, there is no risk of looping and we ensure to follow the shortest
7331 * path to the destination.
7332 *
7333 * It is possible to set <to> to NULL for the first call so that the function
7334 * takes care of visiting the initial frontend in <from>.
7335 *
7336 * It is important to note that the function relies on the fact that all names
7337 * have already been resolved.
7338 */
7339void propagate_processes(struct proxy *from, struct proxy *to)
7340{
7341 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007342
7343 if (to) {
7344 /* check whether we need to go down */
7345 if (from->bind_proc &&
7346 (from->bind_proc & to->bind_proc) == from->bind_proc)
7347 return;
7348
7349 if (!from->bind_proc && !to->bind_proc)
7350 return;
7351
7352 to->bind_proc = from->bind_proc ?
7353 (to->bind_proc | from->bind_proc) : 0;
7354
7355 /* now propagate down */
7356 from = to;
7357 }
7358
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007359 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007360 return;
7361
Willy Tarreauf6b70012014-12-18 14:00:43 +01007362 if (from->state == PR_STSTOPPED)
7363 return;
7364
Willy Tarreau64ab6072014-09-16 12:17:36 +02007365 /* default_backend */
7366 if (from->defbe.be)
7367 propagate_processes(from, from->defbe.be);
7368
7369 /* use_backend */
7370 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007371 if (rule->dynamic)
7372 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007373 to = rule->be.backend;
7374 propagate_processes(from, to);
7375 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007376}
7377
Willy Tarreaubb925012009-07-23 13:36:36 +02007378/*
7379 * Returns the error code, 0 if OK, or any combination of :
7380 * - ERR_ABORT: must abort ASAP
7381 * - ERR_FATAL: we can continue parsing but not start the service
7382 * - ERR_WARN: a warning has been emitted
7383 * - ERR_ALERT: an alert has been emitted
7384 * Only the two first ones can stop processing, the two others are just
7385 * indicators.
7386 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007387int check_config_validity()
7388{
7389 int cfgerr = 0;
7390 struct proxy *curproxy = NULL;
7391 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007392 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007393 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007394 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007395 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007396 struct dns_resolvers *curr_resolvers;
William Lallemand48b4bb42017-10-23 14:36:34 +02007397 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007398
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007399 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007400 /*
7401 * Now, check for the integrity of all that we have collected.
7402 */
7403
7404 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007405 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007406
Willy Tarreau193b8c62012-11-22 00:17:38 +01007407 if (!global.tune.max_http_hdr)
7408 global.tune.max_http_hdr = MAX_HTTP_HDR;
7409
7410 if (!global.tune.cookie_len)
7411 global.tune.cookie_len = CAPTURE_LEN;
7412
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007413 if (!global.tune.requri_len)
7414 global.tune.requri_len = REQURI_LEN;
7415
Emeric Brun96fd9262017-07-05 13:33:16 +02007416 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7417
Willy Tarreau193b8c62012-11-22 00:17:38 +01007418 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7419
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007420 /* allocate pool of resolution per resolvers */
7421 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7422 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7423 /* error message is already displayed by dns_alloc_resolution_pool() */
7424 err_code |= ERR_ALERT | ERR_ABORT;
7425 goto out;
7426 }
7427 }
7428
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007429 /* Post initialisation of the users and groups lists. */
7430 err_code = userlist_postinit();
7431 if (err_code != ERR_NONE)
7432 goto out;
7433
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007434 /* first, we will invert the proxy list order */
7435 curproxy = NULL;
7436 while (proxy) {
7437 struct proxy *next;
7438
7439 next = proxy->next;
7440 proxy->next = curproxy;
7441 curproxy = proxy;
7442 if (!next)
7443 break;
7444 proxy = next;
7445 }
7446
Willy Tarreau419ead82014-09-16 13:41:21 +02007447 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007448 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007449 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007450 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007451 struct act_rule *trule;
7452 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007453 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007454 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007455 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007456
Willy Tarreau050536d2012-10-04 08:47:34 +02007457 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007458 /* proxy ID not set, use automatic numbering with first
7459 * spare entry starting with next_pxid.
7460 */
7461 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7462 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7463 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007464 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007465 next_pxid++;
7466
Willy Tarreau55ea7572007-06-17 19:56:27 +02007467
Willy Tarreaubaaee002006-06-26 02:48:02 +02007468 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007469 /* ensure we don't keep listeners uselessly bound */
7470 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007471 free((void *)curproxy->table.peers.name);
7472 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007473 continue;
7474 }
7475
Willy Tarreau102df612014-05-07 23:56:38 +02007476 /* Check multi-process mode compatibility for the current proxy */
7477
7478 if (curproxy->bind_proc) {
7479 /* an explicit bind-process was specified, let's check how many
7480 * processes remain.
7481 */
David Carliere6c39412015-07-02 07:00:17 +00007482 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007483
7484 curproxy->bind_proc &= nbits(global.nbproc);
7485 if (!curproxy->bind_proc && nbproc == 1) {
7486 Warning("Proxy '%s': the process specified on the 'bind-process' directive refers to a process number that is higher than global.nbproc. The proxy has been forced to run on process 1 only.\n", curproxy->id);
7487 curproxy->bind_proc = 1;
7488 }
7489 else if (!curproxy->bind_proc && nbproc > 1) {
7490 Warning("Proxy '%s': all processes specified on the 'bind-process' directive refer to numbers that are all higher than global.nbproc. The directive was ignored and the proxy will run on all processes.\n", curproxy->id);
7491 curproxy->bind_proc = 0;
7492 }
7493 }
7494
Willy Tarreau3d209582014-05-09 17:06:11 +02007495 /* check and reduce the bind-proc of each listener */
7496 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7497 unsigned long mask;
7498
7499 if (!bind_conf->bind_proc)
7500 continue;
7501
7502 mask = nbits(global.nbproc);
7503 if (curproxy->bind_proc)
7504 mask &= curproxy->bind_proc;
7505 /* mask cannot be null here thanks to the previous checks */
7506
David Carliere6c39412015-07-02 07:00:17 +00007507 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007508 bind_conf->bind_proc &= mask;
7509
7510 if (!bind_conf->bind_proc && nbproc == 1) {
7511 Warning("Proxy '%s': the process number specified on the 'process' directive of 'bind %s' at [%s:%d] refers to a process not covered by the proxy. This has been fixed by forcing it to run on the proxy's first process only.\n",
7512 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7513 bind_conf->bind_proc = mask & ~(mask - 1);
7514 }
7515 else if (!bind_conf->bind_proc && nbproc > 1) {
7516 Warning("Proxy '%s': the process range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to processes not covered by the proxy. The directive was ignored so that all of the proxy's processes are used.\n",
7517 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7518 bind_conf->bind_proc = 0;
7519 }
7520 }
7521
Willy Tarreauff01a212009-03-15 13:46:16 +01007522 switch (curproxy->mode) {
7523 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007524 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007525 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007526 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7527 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007528 cfgerr++;
7529 }
7530
7531 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007532 Warning("config : servers will be ignored for %s '%s'.\n",
7533 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007534 break;
7535
7536 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007537 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007538 break;
7539
7540 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007541 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007542 break;
7543 }
7544
Willy Tarreauf3934b82015-08-11 11:36:45 +02007545 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7546 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7547 proxy_type_str(curproxy), curproxy->id);
7548 err_code |= ERR_WARN;
7549 }
7550
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007551 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007552 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007553 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007554 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7555 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007556 cfgerr++;
7557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007558#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007559 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007560 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7561 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007562 cfgerr++;
7563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007564#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007565 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007566 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7567 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007568 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007569 }
7570 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007571 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007572 /* If no LB algo is set in a backend, and we're not in
7573 * transparent mode, dispatch mode nor proxy mode, we
7574 * want to use balance roundrobin by default.
7575 */
7576 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7577 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007578 }
7579 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007580
Willy Tarreau1620ec32011-08-06 17:05:02 +02007581 if (curproxy->options & PR_O_DISPATCH)
7582 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7583 else if (curproxy->options & PR_O_HTTP_PROXY)
7584 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7585 else if (curproxy->options & PR_O_TRANSP)
7586 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007587
Willy Tarreau1620ec32011-08-06 17:05:02 +02007588 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7589 if (curproxy->options & PR_O_DISABLE404) {
7590 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7591 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7592 err_code |= ERR_WARN;
7593 curproxy->options &= ~PR_O_DISABLE404;
7594 }
7595 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7596 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7597 "send-state", proxy_type_str(curproxy), curproxy->id);
7598 err_code |= ERR_WARN;
7599 curproxy->options &= ~PR_O2_CHK_SNDST;
7600 }
Willy Tarreauef781042010-01-27 11:53:01 +01007601 }
7602
Simon Horman98637e52014-06-20 12:30:16 +09007603 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7604 if (!global.external_check) {
7605 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7606 curproxy->id, "option external-check");
7607 cfgerr++;
7608 }
7609 if (!curproxy->check_command) {
7610 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7611 curproxy->id, "option external-check");
7612 cfgerr++;
7613 }
7614 }
7615
Simon Horman64e34162015-02-06 11:11:57 +09007616 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007617 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7618 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007619 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7620 "'email-alert myhostname', or 'email-alert to' "
7621 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007622 "to be present).\n",
7623 proxy_type_str(curproxy), curproxy->id);
7624 err_code |= ERR_WARN;
7625 free_email_alert(curproxy);
7626 }
7627 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007628 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007629 }
7630
Simon Horman98637e52014-06-20 12:30:16 +09007631 if (curproxy->check_command) {
7632 int clear = 0;
7633 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7634 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7635 "external-check command", proxy_type_str(curproxy), curproxy->id);
7636 err_code |= ERR_WARN;
7637 clear = 1;
7638 }
7639 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007640 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007641 curproxy->id, "external-check command");
7642 cfgerr++;
7643 }
7644 if (clear) {
7645 free(curproxy->check_command);
7646 curproxy->check_command = NULL;
7647 }
7648 }
7649
7650 if (curproxy->check_path) {
7651 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7652 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7653 "external-check path", proxy_type_str(curproxy), curproxy->id);
7654 err_code |= ERR_WARN;
7655 free(curproxy->check_path);
7656 curproxy->check_path = NULL;
7657 }
7658 }
7659
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007660 /* if a default backend was specified, let's find it */
7661 if (curproxy->defbe.name) {
7662 struct proxy *target;
7663
Willy Tarreauafb39922015-05-26 12:04:09 +02007664 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007665 if (!target) {
7666 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7667 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007668 cfgerr++;
7669 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007670 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7671 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007672 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007673 } else if (target->mode != curproxy->mode &&
7674 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7675
7676 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7677 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7678 curproxy->conf.file, curproxy->conf.line,
7679 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7680 target->conf.file, target->conf.line);
7681 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007682 } else {
7683 free(curproxy->defbe.name);
7684 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007685 /* Update tot_fe_maxconn for a further fullconn's computation */
7686 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007687 /* Emit a warning if this proxy also has some servers */
7688 if (curproxy->srv) {
7689 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7690 curproxy->id);
7691 err_code |= ERR_WARN;
7692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007693 }
7694 }
7695
Emeric Brun3f783572017-01-12 11:21:28 +01007696 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7697 /* Case of listen without default backend
7698 * The curproxy will be its own default backend
7699 * so we update tot_fe_maxconn for a further
7700 * fullconn's computation */
7701 curproxy->tot_fe_maxconn += curproxy->maxconn;
7702 }
7703
Willy Tarreau55ea7572007-06-17 19:56:27 +02007704 /* find the target proxy for 'use_backend' rules */
7705 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007706 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007707 struct logformat_node *node;
7708 char *pxname;
7709
7710 /* Try to parse the string as a log format expression. If the result
7711 * of the parsing is only one entry containing a simple string, then
7712 * it's a standard string corresponding to a static rule, thus the
7713 * parsing is cancelled and be.name is restored to be resolved.
7714 */
7715 pxname = rule->be.name;
7716 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007717 curproxy->conf.args.ctx = ARGC_UBK;
7718 curproxy->conf.args.file = rule->file;
7719 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007720 err = NULL;
7721 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7722 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7723 rule->file, rule->line, pxname, err);
7724 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007725 cfgerr++;
7726 continue;
7727 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007728 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7729
7730 if (!LIST_ISEMPTY(&rule->be.expr)) {
7731 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7732 rule->dynamic = 1;
7733 free(pxname);
7734 continue;
7735 }
7736 /* simple string: free the expression and fall back to static rule */
7737 free(node->arg);
7738 free(node);
7739 }
7740
7741 rule->dynamic = 0;
7742 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007743
Willy Tarreauafb39922015-05-26 12:04:09 +02007744 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007745 if (!target) {
7746 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7747 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007748 cfgerr++;
7749 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007750 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7751 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007752 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007753 } else if (target->mode != curproxy->mode &&
7754 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7755
7756 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7757 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7758 curproxy->conf.file, curproxy->conf.line,
7759 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7760 target->conf.file, target->conf.line);
7761 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007762 } else {
7763 free((void *)rule->be.name);
7764 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007765 /* For each target of switching rules, we update
7766 * their tot_fe_maxconn, except if a previous rule point
7767 * on the same backend or on the default backend */
7768 if (rule->be.backend != curproxy->defbe.be) {
7769 struct switching_rule *swrule;
7770
7771 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7772 if (rule == swrule) {
7773 target->tot_fe_maxconn += curproxy->maxconn;
7774 break;
7775 }
7776 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7777 /* there is multiple ref of this backend */
7778 break;
7779 }
7780 }
7781 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007782 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007783 }
7784
Willy Tarreau64ab6072014-09-16 12:17:36 +02007785 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007786 list_for_each_entry(srule, &curproxy->server_rules, list) {
7787 struct server *target = findserver(curproxy, srule->srv.name);
7788
7789 if (!target) {
7790 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7791 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7792 cfgerr++;
7793 continue;
7794 }
7795 free((void *)srule->srv.name);
7796 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007797 }
7798
Emeric Brunb982a3d2010-01-04 15:45:53 +01007799 /* find the target table for 'stick' rules */
7800 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7801 struct proxy *target;
7802
Emeric Brun1d33b292010-01-04 15:47:17 +01007803 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7804 if (mrule->flags & STK_IS_STORE)
7805 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7806
Emeric Brunb982a3d2010-01-04 15:45:53 +01007807 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007808 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007809 else
7810 target = curproxy;
7811
7812 if (!target) {
7813 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7814 curproxy->id, mrule->table.name);
7815 cfgerr++;
7816 }
7817 else if (target->table.size == 0) {
7818 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7819 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7820 cfgerr++;
7821 }
Willy Tarreau12785782012-04-27 21:37:17 +02007822 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7823 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007824 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7825 cfgerr++;
7826 }
7827 else {
7828 free((void *)mrule->table.name);
7829 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007830 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007831 }
7832 }
7833
7834 /* find the target table for 'store response' rules */
7835 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7836 struct proxy *target;
7837
Emeric Brun1d33b292010-01-04 15:47:17 +01007838 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7839
Emeric Brunb982a3d2010-01-04 15:45:53 +01007840 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007841 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007842 else
7843 target = curproxy;
7844
7845 if (!target) {
7846 Alert("Proxy '%s': unable to find store table '%s'.\n",
7847 curproxy->id, mrule->table.name);
7848 cfgerr++;
7849 }
7850 else if (target->table.size == 0) {
7851 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7852 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7853 cfgerr++;
7854 }
Willy Tarreau12785782012-04-27 21:37:17 +02007855 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7856 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007857 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7858 cfgerr++;
7859 }
7860 else {
7861 free((void *)mrule->table.name);
7862 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007863 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007864 }
7865 }
7866
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007867 /* find the target table for 'tcp-request' layer 4 rules */
7868 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7869 struct proxy *target;
7870
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007871 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007872 continue;
7873
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007874 if (trule->arg.trk_ctr.table.n)
7875 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007876 else
7877 target = curproxy;
7878
7879 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007880 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007881 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007882 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007883 cfgerr++;
7884 }
7885 else if (target->table.size == 0) {
7886 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007887 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007888 cfgerr++;
7889 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007890 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007891 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007892 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007893 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007894 cfgerr++;
7895 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007896 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007897 free(trule->arg.trk_ctr.table.n);
7898 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007899 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007900 * to pass a list of counters to track and allocate them right here using
7901 * stktable_alloc_data_type().
7902 */
7903 }
7904 }
7905
Willy Tarreau620408f2016-10-21 16:37:51 +02007906 /* find the target table for 'tcp-request' layer 5 rules */
7907 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7908 struct proxy *target;
7909
7910 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7911 continue;
7912
7913 if (trule->arg.trk_ctr.table.n)
7914 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7915 else
7916 target = curproxy;
7917
7918 if (!target) {
7919 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7920 curproxy->id, trule->arg.trk_ctr.table.n,
7921 tcp_trk_idx(trule->action));
7922 cfgerr++;
7923 }
7924 else if (target->table.size == 0) {
7925 Alert("Proxy '%s': table '%s' used but not configured.\n",
7926 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7927 cfgerr++;
7928 }
7929 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7930 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7931 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7932 tcp_trk_idx(trule->action));
7933 cfgerr++;
7934 }
7935 else {
7936 free(trule->arg.trk_ctr.table.n);
7937 trule->arg.trk_ctr.table.t = &target->table;
7938 /* Note: if we decide to enhance the track-sc syntax, we may be able
7939 * to pass a list of counters to track and allocate them right here using
7940 * stktable_alloc_data_type().
7941 */
7942 }
7943 }
7944
Willy Tarreaud1f96522010-08-03 19:34:32 +02007945 /* find the target table for 'tcp-request' layer 6 rules */
7946 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7947 struct proxy *target;
7948
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007949 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007950 continue;
7951
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007952 if (trule->arg.trk_ctr.table.n)
7953 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007954 else
7955 target = curproxy;
7956
7957 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007958 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007959 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007960 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007961 cfgerr++;
7962 }
7963 else if (target->table.size == 0) {
7964 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007965 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007966 cfgerr++;
7967 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007968 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007969 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007970 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007971 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007972 cfgerr++;
7973 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007974 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007975 free(trule->arg.trk_ctr.table.n);
7976 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007977 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007978 * to pass a list of counters to track and allocate them right here using
7979 * stktable_alloc_data_type().
7980 */
7981 }
7982 }
7983
Baptiste Assmanne9544932015-11-03 23:31:35 +01007984 /* parse http-request capture rules to ensure id really exists */
7985 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7986 if (hrqrule->action != ACT_CUSTOM ||
7987 hrqrule->action_ptr != http_action_req_capture_by_id)
7988 continue;
7989
7990 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7991 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7992 curproxy->id, hrqrule->arg.capid.idx);
7993 cfgerr++;
7994 }
7995 }
7996
7997 /* parse http-response capture rules to ensure id really exists */
7998 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7999 if (hrqrule->action != ACT_CUSTOM ||
8000 hrqrule->action_ptr != http_action_res_capture_by_id)
8001 continue;
8002
8003 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8004 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8005 curproxy->id, hrqrule->arg.capid.idx);
8006 cfgerr++;
8007 }
8008 }
8009
Willy Tarreau09448f72014-06-25 18:12:15 +02008010 /* find the target table for 'http-request' layer 7 rules */
8011 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8012 struct proxy *target;
8013
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008014 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008015 continue;
8016
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008017 if (hrqrule->arg.trk_ctr.table.n)
8018 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008019 else
8020 target = curproxy;
8021
8022 if (!target) {
8023 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008024 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008025 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008026 cfgerr++;
8027 }
8028 else if (target->table.size == 0) {
8029 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008030 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008031 cfgerr++;
8032 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008033 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008034 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008035 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008036 http_trk_idx(hrqrule->action));
8037 cfgerr++;
8038 }
8039 else {
8040 free(hrqrule->arg.trk_ctr.table.n);
8041 hrqrule->arg.trk_ctr.table.t = &target->table;
8042 /* Note: if we decide to enhance the track-sc syntax, we may be able
8043 * to pass a list of counters to track and allocate them right here using
8044 * stktable_alloc_data_type().
8045 */
8046 }
8047 }
8048
8049 /* find the target table for 'http-response' layer 7 rules */
8050 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8051 struct proxy *target;
8052
8053 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8054 continue;
8055
8056 if (hrqrule->arg.trk_ctr.table.n)
8057 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8058 else
8059 target = curproxy;
8060
8061 if (!target) {
8062 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8063 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8064 http_trk_idx(hrqrule->action));
8065 cfgerr++;
8066 }
8067 else if (target->table.size == 0) {
8068 Alert("Proxy '%s': table '%s' used but not configured.\n",
8069 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8070 cfgerr++;
8071 }
8072 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8073 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8074 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8075 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008076 cfgerr++;
8077 }
8078 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008079 free(hrqrule->arg.trk_ctr.table.n);
8080 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008081 /* Note: if we decide to enhance the track-sc syntax, we may be able
8082 * to pass a list of counters to track and allocate them right here using
8083 * stktable_alloc_data_type().
8084 */
8085 }
8086 }
8087
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008088 /* move any "block" rules at the beginning of the http-request rules */
8089 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8090 /* insert block_rules into http_req_rules at the beginning */
8091 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8092 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8093 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8094 curproxy->http_req_rules.n = curproxy->block_rules.n;
8095 LIST_INIT(&curproxy->block_rules);
8096 }
8097
Emeric Brun32da3c42010-09-23 18:39:19 +02008098 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008099 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008100
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008101 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008102 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8103 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008104 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008105 break;
8106 }
8107 }
8108
8109 if (!curpeers) {
8110 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8111 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008112 free((void *)curproxy->table.peers.name);
8113 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008114 cfgerr++;
8115 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008116 else if (curpeers->state == PR_STSTOPPED) {
8117 /* silently disable this peers section */
8118 curproxy->table.peers.p = NULL;
8119 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008120 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008121 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8122 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008123 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008124 cfgerr++;
8125 }
8126 }
8127
Simon Horman9dc49962015-01-30 11:22:59 +09008128
8129 if (curproxy->email_alert.mailers.name) {
8130 struct mailers *curmailers = mailers;
8131
8132 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8133 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8134 free(curproxy->email_alert.mailers.name);
8135 curproxy->email_alert.mailers.m = curmailers;
8136 curmailers->users++;
8137 break;
8138 }
8139 }
8140
8141 if (!curmailers) {
8142 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8143 curproxy->id, curproxy->email_alert.mailers.name);
8144 free_email_alert(curproxy);
8145 cfgerr++;
8146 }
8147 }
8148
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008149 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008150 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008151 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8152 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8153 "proxy", curproxy->id);
8154 cfgerr++;
8155 goto out_uri_auth_compat;
8156 }
8157
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008158 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008159 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008160 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008161 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008162
Willy Tarreau95fa4692010-02-01 13:05:50 +01008163 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8164 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008165
8166 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008167 uri_auth_compat_req[i++] = "realm";
8168 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8169 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008170
Willy Tarreau95fa4692010-02-01 13:05:50 +01008171 uri_auth_compat_req[i++] = "unless";
8172 uri_auth_compat_req[i++] = "{";
8173 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8174 uri_auth_compat_req[i++] = "}";
8175 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008176
Willy Tarreauff011f22011-01-06 17:51:27 +01008177 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8178 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008179 cfgerr++;
8180 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008181 }
8182
Willy Tarreauff011f22011-01-06 17:51:27 +01008183 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008184
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008185 if (curproxy->uri_auth->auth_realm) {
8186 free(curproxy->uri_auth->auth_realm);
8187 curproxy->uri_auth->auth_realm = NULL;
8188 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008189
8190 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008191 }
8192out_uri_auth_compat:
8193
Dragan Dosen43885c72015-10-01 13:18:13 +02008194 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008195 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008196 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8197 if (!curproxy->conf.logformat_sd_string) {
8198 /* set the default logformat_sd_string */
8199 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8200 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008201 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008202 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008203 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008204
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008205 /* compile the log format */
8206 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008207 if (curproxy->conf.logformat_string != default_http_log_format &&
8208 curproxy->conf.logformat_string != default_tcp_log_format &&
8209 curproxy->conf.logformat_string != clf_http_log_format)
8210 free(curproxy->conf.logformat_string);
8211 curproxy->conf.logformat_string = NULL;
8212 free(curproxy->conf.lfs_file);
8213 curproxy->conf.lfs_file = NULL;
8214 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008215
8216 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8217 free(curproxy->conf.logformat_sd_string);
8218 curproxy->conf.logformat_sd_string = NULL;
8219 free(curproxy->conf.lfsd_file);
8220 curproxy->conf.lfsd_file = NULL;
8221 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008222 }
8223
Willy Tarreau62a61232013-04-12 18:13:46 +02008224 if (curproxy->conf.logformat_string) {
8225 curproxy->conf.args.ctx = ARGC_LOG;
8226 curproxy->conf.args.file = curproxy->conf.lfs_file;
8227 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008228 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008229 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008230 SMP_VAL_FE_LOG_END, &err)) {
8231 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8232 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8233 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008234 cfgerr++;
8235 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008236 curproxy->conf.args.file = NULL;
8237 curproxy->conf.args.line = 0;
8238 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008239
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008240 if (curproxy->conf.logformat_sd_string) {
8241 curproxy->conf.args.ctx = ARGC_LOGSD;
8242 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8243 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008244 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008245 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 +01008246 SMP_VAL_FE_LOG_END, &err)) {
8247 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8248 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8249 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008250 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008251 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8252 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8253 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8254 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008255 cfgerr++;
8256 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008257 curproxy->conf.args.file = NULL;
8258 curproxy->conf.args.line = 0;
8259 }
8260
Willy Tarreau62a61232013-04-12 18:13:46 +02008261 if (curproxy->conf.uniqueid_format_string) {
8262 curproxy->conf.args.ctx = ARGC_UIF;
8263 curproxy->conf.args.file = curproxy->conf.uif_file;
8264 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008265 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008266 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 +01008267 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8268 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8269 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8270 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008271 cfgerr++;
8272 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008273 curproxy->conf.args.file = NULL;
8274 curproxy->conf.args.line = 0;
8275 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008276
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008277 /* only now we can check if some args remain unresolved.
8278 * This must be done after the users and groups resolution.
8279 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008280 cfgerr += smp_resolve_args(curproxy);
8281 if (!cfgerr)
8282 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008283
Willy Tarreau2738a142006-07-08 17:28:09 +02008284 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008285 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008286 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008287 (!curproxy->timeout.connect ||
8288 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008289 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008290 " | While not properly invalid, you will certainly encounter various problems\n"
8291 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008292 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008293 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008294 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008295 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008296
Willy Tarreau1fa31262007-12-03 00:36:16 +01008297 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8298 * We must still support older configurations, so let's find out whether those
8299 * parameters have been set or must be copied from contimeouts.
8300 */
8301 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008302 if (!curproxy->timeout.tarpit ||
8303 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008304 /* tarpit timeout not set. We search in the following order:
8305 * default.tarpit, curr.connect, default.connect.
8306 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008307 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008308 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008309 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008310 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008311 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008312 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008313 }
8314 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008315 (!curproxy->timeout.queue ||
8316 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008317 /* queue timeout not set. We search in the following order:
8318 * default.queue, curr.connect, default.connect.
8319 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008320 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008321 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008322 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008323 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008324 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008325 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008326 }
8327 }
8328
Willy Tarreau1620ec32011-08-06 17:05:02 +02008329 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008330 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008331 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008332 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008333 }
8334
Willy Tarreau215663d2014-06-13 18:30:23 +02008335 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8336 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8337 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8338 proxy_type_str(curproxy), curproxy->id);
8339 err_code |= ERR_WARN;
8340 }
8341
Willy Tarreau193b8c62012-11-22 00:17:38 +01008342 /* ensure that cookie capture length is not too large */
8343 if (curproxy->capture_len >= global.tune.cookie_len) {
8344 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8345 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8346 err_code |= ERR_WARN;
8347 curproxy->capture_len = global.tune.cookie_len - 1;
8348 }
8349
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008350 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008351 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008352 curproxy->req_cap_pool = create_pool("ptrcap",
8353 curproxy->nb_req_cap * sizeof(char *),
8354 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008355 }
8356
8357 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008358 curproxy->rsp_cap_pool = create_pool("ptrcap",
8359 curproxy->nb_rsp_cap * sizeof(char *),
8360 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008361 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008362
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008363 switch (curproxy->load_server_state_from_file) {
8364 case PR_SRV_STATE_FILE_UNSPEC:
8365 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8366 break;
8367 case PR_SRV_STATE_FILE_GLOBAL:
8368 if (!global.server_state_file) {
8369 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",
8370 curproxy->id);
8371 err_code |= ERR_WARN;
8372 }
8373 break;
8374 }
8375
Willy Tarreaubaaee002006-06-26 02:48:02 +02008376 /* first, we will invert the servers list order */
8377 newsrv = NULL;
8378 while (curproxy->srv) {
8379 struct server *next;
8380
8381 next = curproxy->srv->next;
8382 curproxy->srv->next = newsrv;
8383 newsrv = curproxy->srv;
8384 if (!next)
8385 break;
8386 curproxy->srv = next;
8387 }
8388
Willy Tarreau17edc812014-01-03 12:14:34 +01008389 /* Check that no server name conflicts. This causes trouble in the stats.
8390 * We only emit a warning for the first conflict affecting each server,
8391 * in order to avoid combinatory explosion if all servers have the same
8392 * name. We do that only for servers which do not have an explicit ID,
8393 * because these IDs were made also for distinguishing them and we don't
8394 * want to annoy people who correctly manage them.
8395 */
8396 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8397 struct server *other_srv;
8398
8399 if (newsrv->puid)
8400 continue;
8401
8402 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8403 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8404 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8405 newsrv->conf.file, newsrv->conf.line,
8406 proxy_type_str(curproxy), curproxy->id,
8407 newsrv->id, other_srv->conf.line);
8408 break;
8409 }
8410 }
8411 }
8412
Willy Tarreaudd701652010-05-25 23:03:02 +02008413 /* assign automatic UIDs to servers which don't have one yet */
8414 next_id = 1;
8415 newsrv = curproxy->srv;
8416 while (newsrv != NULL) {
8417 if (!newsrv->puid) {
8418 /* server ID not set, use automatic numbering with first
8419 * spare entry starting with next_svid.
8420 */
8421 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8422 newsrv->conf.id.key = newsrv->puid = next_id;
8423 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8424 }
8425 next_id++;
8426 newsrv = newsrv->next;
8427 }
8428
Willy Tarreau20697042007-11-15 23:26:18 +01008429 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008430 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008431
Willy Tarreau62c3be22012-01-20 13:12:32 +01008432 /*
8433 * If this server supports a maxconn parameter, it needs a dedicated
8434 * tasks to fill the emptied slots when a connection leaves.
8435 * Also, resolve deferred tracking dependency if needed.
8436 */
8437 newsrv = curproxy->srv;
8438 while (newsrv != NULL) {
8439 if (newsrv->minconn > newsrv->maxconn) {
8440 /* Only 'minconn' was specified, or it was higher than or equal
8441 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8442 * this will avoid further useless expensive computations.
8443 */
8444 newsrv->maxconn = newsrv->minconn;
8445 } else if (newsrv->maxconn && !newsrv->minconn) {
8446 /* minconn was not specified, so we set it to maxconn */
8447 newsrv->minconn = newsrv->maxconn;
8448 }
8449
Willy Tarreau17d45382016-12-22 21:16:08 +01008450 /* this will also properly set the transport layer for prod and checks */
8451 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8452 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8453 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8454 }
Emeric Brun94324a42012-10-11 14:00:19 +02008455
Willy Tarreau2f075e92013-12-03 11:11:34 +01008456 /* set the check type on the server */
8457 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8458
Willy Tarreau62c3be22012-01-20 13:12:32 +01008459 if (newsrv->trackit) {
8460 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008461 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008462 char *pname, *sname;
8463
8464 pname = newsrv->trackit;
8465 sname = strrchr(pname, '/');
8466
8467 if (sname)
8468 *sname++ = '\0';
8469 else {
8470 sname = pname;
8471 pname = NULL;
8472 }
8473
8474 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008475 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008476 if (!px) {
8477 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8478 proxy_type_str(curproxy), curproxy->id,
8479 newsrv->id, pname);
8480 cfgerr++;
8481 goto next_srv;
8482 }
8483 } else
8484 px = curproxy;
8485
8486 srv = findserver(px, sname);
8487 if (!srv) {
8488 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8489 proxy_type_str(curproxy), curproxy->id,
8490 newsrv->id, sname);
8491 cfgerr++;
8492 goto next_srv;
8493 }
8494
Willy Tarreau32091232014-05-16 13:52:00 +02008495 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8496 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8497 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008498 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008499 "tracking as it does not have any check nor agent enabled.\n",
8500 proxy_type_str(curproxy), curproxy->id,
8501 newsrv->id, px->id, srv->id);
8502 cfgerr++;
8503 goto next_srv;
8504 }
8505
8506 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8507
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008508 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008509 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8510 "belongs to a tracking chain looping back to %s/%s.\n",
8511 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008512 newsrv->id, px->id, srv->id, px->id,
8513 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008514 cfgerr++;
8515 goto next_srv;
8516 }
8517
8518 if (curproxy != px &&
8519 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8520 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8521 "tracking: disable-on-404 option inconsistency.\n",
8522 proxy_type_str(curproxy), curproxy->id,
8523 newsrv->id, px->id, srv->id);
8524 cfgerr++;
8525 goto next_srv;
8526 }
8527
Willy Tarreau62c3be22012-01-20 13:12:32 +01008528 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008529 newsrv->tracknext = srv->trackers;
8530 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008531
8532 free(newsrv->trackit);
8533 newsrv->trackit = NULL;
8534 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008535
8536 /*
8537 * resolve server's resolvers name and update the resolvers pointer
8538 * accordingly
8539 */
8540 if (newsrv->resolvers_id) {
8541 struct dns_resolvers *curr_resolvers;
8542 int found;
8543
8544 found = 0;
8545 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8546 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8547 found = 1;
8548 break;
8549 }
8550 }
8551
8552 if (!found) {
8553 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8554 proxy_type_str(curproxy), curproxy->id,
8555 newsrv->id, newsrv->resolvers_id);
8556 cfgerr++;
8557 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008558 if (newsrv->srvrq) {
8559 if (!newsrv->srvrq->resolvers) {
8560 newsrv->srvrq->resolvers = curr_resolvers;
8561 if (dns_link_resolution(newsrv->srvrq,
8562 OBJ_TYPE_SRVRQ, NULL) != 0) {
8563 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8564 proxy_type_str(curproxy), curproxy->id,
8565 newsrv->id);
8566 cfgerr++;
8567 }
8568 }
8569
8570 }
8571 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008572 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008573 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8574 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8575 proxy_type_str(curproxy), curproxy->id,
8576 newsrv->id);
8577 cfgerr++;
8578 }
8579 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008580 }
8581 }
8582 else {
8583 /* if no resolvers section associated to this server
8584 * we can clean up the associated resolution structure
8585 */
8586 if (newsrv->resolution) {
8587 free(newsrv->resolution->hostname_dn);
8588 newsrv->resolution->hostname_dn = NULL;
8589 free(newsrv->resolution);
8590 newsrv->resolution = NULL;
8591 }
8592 }
8593
Willy Tarreau62c3be22012-01-20 13:12:32 +01008594 next_srv:
8595 newsrv = newsrv->next;
8596 }
8597
Olivier Houchard4e694042017-03-14 20:01:29 +01008598 /*
8599 * Try to generate dynamic cookies for servers now.
8600 * It couldn't be done earlier, since at the time we parsed
8601 * the server line, we may not have known yet that we
8602 * should use dynamic cookies, or the secret key may not
8603 * have been provided yet.
8604 */
8605 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8606 newsrv = curproxy->srv;
8607 while (newsrv != NULL) {
8608 srv_set_dyncookie(newsrv);
8609 newsrv = newsrv->next;
8610 }
8611
8612 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008613 /* We have to initialize the server lookup mechanism depending
8614 * on what LB algorithm was choosen.
8615 */
8616
8617 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8618 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8619 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008620 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8621 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8622 init_server_map(curproxy);
8623 } else {
8624 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8625 fwrr_init_server_groups(curproxy);
8626 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008627 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008628
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008629 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008630 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8631 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8632 fwlc_init_server_tree(curproxy);
8633 } else {
8634 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8635 fas_init_server_tree(curproxy);
8636 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008637 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008638
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008639 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008640 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8641 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8642 chash_init_server_tree(curproxy);
8643 } else {
8644 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8645 init_server_map(curproxy);
8646 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008647 break;
8648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008649
8650 if (curproxy->options & PR_O_LOGASAP)
8651 curproxy->to_log &= ~LW_BYTES;
8652
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008653 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008654 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8655 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008656 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8657 proxy_type_str(curproxy), curproxy->id);
8658 err_code |= ERR_WARN;
8659 }
8660
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008661 if (curproxy->mode != PR_MODE_HTTP) {
8662 int optnum;
8663
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008664 if (curproxy->uri_auth) {
8665 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8666 proxy_type_str(curproxy), curproxy->id);
8667 err_code |= ERR_WARN;
8668 curproxy->uri_auth = NULL;
8669 }
8670
Willy Tarreaude7dc882017-03-10 11:49:21 +01008671 if (curproxy->capture_name) {
8672 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8673 proxy_type_str(curproxy), curproxy->id);
8674 err_code |= ERR_WARN;
8675 }
8676
8677 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8678 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8679 proxy_type_str(curproxy), curproxy->id);
8680 err_code |= ERR_WARN;
8681 }
8682
8683 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8684 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8685 proxy_type_str(curproxy), curproxy->id);
8686 err_code |= ERR_WARN;
8687 }
8688
8689 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8690 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8691 proxy_type_str(curproxy), curproxy->id);
8692 err_code |= ERR_WARN;
8693 }
8694
8695 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8696 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8697 proxy_type_str(curproxy), curproxy->id);
8698 err_code |= ERR_WARN;
8699 }
8700
Willy Tarreau87cf5142011-08-19 22:57:24 +02008701 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008702 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8703 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8704 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008705 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008706 }
8707
8708 if (curproxy->options & PR_O_ORGTO) {
8709 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8710 "originalto", proxy_type_str(curproxy), curproxy->id);
8711 err_code |= ERR_WARN;
8712 curproxy->options &= ~PR_O_ORGTO;
8713 }
8714
8715 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8716 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8717 (curproxy->cap & cfg_opts[optnum].cap) &&
8718 (curproxy->options & cfg_opts[optnum].val)) {
8719 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8720 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8721 err_code |= ERR_WARN;
8722 curproxy->options &= ~cfg_opts[optnum].val;
8723 }
8724 }
8725
8726 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8727 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8728 (curproxy->cap & cfg_opts2[optnum].cap) &&
8729 (curproxy->options2 & cfg_opts2[optnum].val)) {
8730 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8731 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8732 err_code |= ERR_WARN;
8733 curproxy->options2 &= ~cfg_opts2[optnum].val;
8734 }
8735 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008736
Willy Tarreau29fbe512015-08-20 19:35:14 +02008737#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008738 if (curproxy->conn_src.bind_hdr_occ) {
8739 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008740 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008741 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008742 err_code |= ERR_WARN;
8743 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008744#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008745 }
8746
Willy Tarreaubaaee002006-06-26 02:48:02 +02008747 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008748 * ensure that we're not cross-dressing a TCP server into HTTP.
8749 */
8750 newsrv = curproxy->srv;
8751 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008752 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008753 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8754 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008755 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008756 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008757
Willy Tarreau0cec3312011-10-31 13:49:26 +01008758 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8759 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8760 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8761 err_code |= ERR_WARN;
8762 }
8763
Willy Tarreauc93cd162014-05-13 15:54:22 +02008764 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008765 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8766 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8767 err_code |= ERR_WARN;
8768 }
8769
Willy Tarreau29fbe512015-08-20 19:35:14 +02008770#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008771 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8772 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008773 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 +01008774 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008775 err_code |= ERR_WARN;
8776 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008777#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008778
8779 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8780 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8781 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8782 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8783 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8784 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",
8785 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8786 err_code |= ERR_WARN;
8787 }
8788
8789
8790 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8791 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",
8792 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8793 err_code |= ERR_WARN;
8794 }
8795 }
8796
Willy Tarreau21d2af32008-02-14 20:25:24 +01008797 newsrv = newsrv->next;
8798 }
8799
Willy Tarreaue42bd962014-09-16 16:21:19 +02008800 /* check if we have a frontend with "tcp-request content" looking at L7
8801 * with no inspect-delay
8802 */
8803 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8804 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008805 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008806 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008807 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008808 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008809 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008810 break;
8811 }
8812
8813 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8814 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8815 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8816 " This means that these rules will randomly find their contents. This can be fixed by"
8817 " setting the tcp-request inspect-delay.\n",
8818 proxy_type_str(curproxy), curproxy->id);
8819 err_code |= ERR_WARN;
8820 }
8821 }
8822
Christopher Fauletd7c91962015-04-30 11:48:27 +02008823 /* Check filter configuration, if any */
8824 cfgerr += flt_check(curproxy);
8825
Willy Tarreauc1a21672009-08-16 22:37:44 +02008826 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008827 if (!curproxy->accept)
8828 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008829
Willy Tarreauc1a21672009-08-16 22:37:44 +02008830 if (curproxy->tcp_req.inspect_delay ||
8831 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008832 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008833
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008834 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008835 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008836 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008837 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008838
8839 /* both TCP and HTTP must check switching rules */
8840 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008841
8842 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008843 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008844 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8845 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 +01008846 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008847 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8848 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008849 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008850 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008851 }
8852
8853 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008854 if (curproxy->tcp_req.inspect_delay ||
8855 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8856 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8857
Emeric Brun97679e72010-09-23 17:56:44 +02008858 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8859 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8860
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008861 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008862 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008863 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008864 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008865
8866 /* If the backend does requires RDP cookie persistence, we have to
8867 * enable the corresponding analyser.
8868 */
8869 if (curproxy->options2 & PR_O2_RDPC_PRST)
8870 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008871
8872 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008873 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008874 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8875 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 +01008876 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008877 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8878 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008879 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008880 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008881 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008882 }
8883
8884 /***********************************************************/
8885 /* At this point, target names have already been resolved. */
8886 /***********************************************************/
8887
8888 /* Check multi-process mode compatibility */
8889
8890 if (global.nbproc > 1 && global.stats_fe) {
8891 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8892 unsigned long mask;
8893
8894 mask = nbits(global.nbproc);
8895 if (global.stats_fe->bind_proc)
8896 mask &= global.stats_fe->bind_proc;
8897
8898 if (bind_conf->bind_proc)
8899 mask &= bind_conf->bind_proc;
8900
8901 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008902 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008903 break;
8904 }
8905 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8906 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");
8907 }
8908 }
8909
8910 /* Make each frontend inherit bind-process from its listeners when not specified. */
8911 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8912 if (curproxy->bind_proc)
8913 continue;
8914
8915 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8916 unsigned long mask;
8917
Willy Tarreaue428b082015-05-04 21:57:58 +02008918 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008919 curproxy->bind_proc |= mask;
8920 }
8921
8922 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008923 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008924 }
8925
8926 if (global.stats_fe) {
8927 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8928 unsigned long mask;
8929
Cyril Bonté06181952016-02-24 00:14:54 +01008930 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008931 global.stats_fe->bind_proc |= mask;
8932 }
8933 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008934 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008935 }
8936
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008937 /* propagate bindings from frontends to backends. Don't do it if there
8938 * are any fatal errors as we must not call it with unresolved proxies.
8939 */
8940 if (!cfgerr) {
8941 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8942 if (curproxy->cap & PR_CAP_FE)
8943 propagate_processes(curproxy, NULL);
8944 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008945 }
8946
8947 /* Bind each unbound backend to all processes when not specified. */
8948 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8949 if (curproxy->bind_proc)
8950 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008951 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008952 }
8953
8954 /*******************************************************/
8955 /* At this step, all proxies have a non-null bind_proc */
8956 /*******************************************************/
8957
8958 /* perform the final checks before creating tasks */
8959
8960 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8961 struct listener *listener;
8962 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008963
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008964 /* Configure SSL for each bind line.
8965 * Note: if configuration fails at some point, the ->ctx member
8966 * remains NULL so that listeners can later detach.
8967 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008968 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008969 if (bind_conf->xprt->prepare_bind_conf &&
8970 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008971 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008972 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008973
Willy Tarreaue6b98942007-10-29 01:09:36 +01008974 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008975 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008976 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008977 int nbproc;
8978
8979 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008980 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008981 nbits(global.nbproc));
8982
8983 if (!nbproc) /* no intersection between listener and frontend */
8984 nbproc = 1;
8985
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008986 if (!listener->luid) {
8987 /* listener ID not set, use automatic numbering with first
8988 * spare entry starting with next_luid.
8989 */
8990 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8991 listener->conf.id.key = listener->luid = next_id;
8992 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008993 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008994 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008995
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008996 /* enable separate counters */
8997 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008998 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008999 if (!listener->name)
9000 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009001 }
Willy Tarreau81796be2012-09-22 19:11:47 +02009002
Willy Tarreaue6b98942007-10-29 01:09:36 +01009003 if (curproxy->options & PR_O_TCP_NOLING)
9004 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02009005 if (!listener->maxconn)
9006 listener->maxconn = curproxy->maxconn;
9007 if (!listener->backlog)
9008 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01009009 if (!listener->maxaccept)
9010 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
9011
9012 /* we want to have an optimal behaviour on single process mode to
9013 * maximize the work at once, but in multi-process we want to keep
9014 * some fairness between processes, so we target half of the max
9015 * number of events to be balanced over all the processes the proxy
9016 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9017 * used to disable the limit.
9018 */
9019 if (listener->maxaccept > 0) {
9020 if (nbproc > 1)
9021 listener->maxaccept = (listener->maxaccept + 1) / 2;
9022 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9023 }
9024
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009025 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009026 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009027 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009028
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009029 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009030 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009031
Willy Tarreau620408f2016-10-21 16:37:51 +02009032 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9033 listener->options |= LI_O_TCP_L5_RULES;
9034
Willy Tarreaude3041d2010-05-31 10:56:17 +02009035 if (curproxy->mon_mask.s_addr)
9036 listener->options |= LI_O_CHK_MONNET;
9037
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009038 /* smart accept mode is automatic in HTTP mode */
9039 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009040 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009041 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9042 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009043 }
9044
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009045 /* Release unused SSL configs */
9046 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009047 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9048 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009049 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009050
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009051 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009052 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009053 int count, maxproc = 0;
9054
9055 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009056 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009057 if (count > maxproc)
9058 maxproc = count;
9059 }
9060 /* backends have 0, frontends have 1 or more */
9061 if (maxproc != 1)
9062 Warning("Proxy '%s': in multi-process mode, stats will be"
9063 " limited to process assigned to the current request.\n",
9064 curproxy->id);
9065
Willy Tarreau102df612014-05-07 23:56:38 +02009066 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9067 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9068 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009069 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009070 }
Willy Tarreau102df612014-05-07 23:56:38 +02009071 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9072 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9073 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009074 }
9075 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009076
9077 /* create the task associated with the proxy */
9078 curproxy->task = task_new();
9079 if (curproxy->task) {
9080 curproxy->task->context = curproxy;
9081 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009082 } else {
9083 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9084 curproxy->id);
9085 cfgerr++;
9086 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009087 }
9088
Willy Tarreaufbb78422011-06-05 15:38:35 +02009089 /* automatically compute fullconn if not set. We must not do it in the
9090 * loop above because cross-references are not yet fully resolved.
9091 */
9092 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9093 /* If <fullconn> is not set, let's set it to 10% of the sum of
9094 * the possible incoming frontend's maxconns.
9095 */
9096 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009097 /* we have the sum of the maxconns in <total>. We only
9098 * keep 10% of that sum to set the default fullconn, with
9099 * a hard minimum of 1 (to avoid a divide by zero).
9100 */
Emeric Brun3f783572017-01-12 11:21:28 +01009101 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009102 if (!curproxy->fullconn)
9103 curproxy->fullconn = 1;
9104 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009105 }
9106
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009107 /*
9108 * Recount currently required checks.
9109 */
9110
9111 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9112 int optnum;
9113
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009114 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9115 if (curproxy->options & cfg_opts[optnum].val)
9116 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009117
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009118 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9119 if (curproxy->options2 & cfg_opts2[optnum].val)
9120 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009121 }
9122
Willy Tarreau0fca4832015-05-01 19:12:05 +02009123 /* compute the required process bindings for the peers */
9124 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9125 if (curproxy->table.peers.p)
9126 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9127
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009128 if (cfg_peers) {
9129 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009130 struct peer *p, *pb;
9131
Willy Tarreau1e273012015-05-01 19:15:17 +02009132 /* Remove all peers sections which don't have a valid listener,
9133 * which are not used by any table, or which are bound to more
9134 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009135 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009136 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009137 while (*last) {
9138 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009139
9140 if (curpeers->state == PR_STSTOPPED) {
9141 /* the "disabled" keyword was present */
9142 if (curpeers->peers_fe)
9143 stop_proxy(curpeers->peers_fe);
9144 curpeers->peers_fe = NULL;
9145 }
9146 else if (!curpeers->peers_fe) {
9147 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9148 curpeers->id, localpeer);
9149 }
David Carliere6c39412015-07-02 07:00:17 +00009150 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009151 /* either it's totally stopped or too much used */
9152 if (curpeers->peers_fe->bind_proc) {
9153 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009154 "running in different processes (%d different ones). "
9155 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009156 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009157 cfgerr++;
9158 }
9159 stop_proxy(curpeers->peers_fe);
9160 curpeers->peers_fe = NULL;
9161 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009162 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009163 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009164 last = &curpeers->next;
9165 continue;
9166 }
9167
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009168 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009169 p = curpeers->remote;
9170 while (p) {
9171 pb = p->next;
9172 free(p->id);
9173 free(p);
9174 p = pb;
9175 }
9176
9177 /* Destroy and unlink this curpeers section.
9178 * Note: curpeers is backed up into *last.
9179 */
9180 free(curpeers->id);
9181 curpeers = curpeers->next;
9182 free(*last);
9183 *last = curpeers;
9184 }
9185 }
9186
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009187 /* initialize stick-tables on backend capable proxies. This must not
9188 * be done earlier because the data size may be discovered while parsing
9189 * other proxies.
9190 */
9191 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9192 if (curproxy->state == PR_STSTOPPED)
9193 continue;
9194
9195 if (!stktable_init(&curproxy->table)) {
9196 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9197 cfgerr++;
9198 }
9199 }
9200
Simon Horman0d16a402015-01-30 11:22:58 +09009201 if (mailers) {
9202 struct mailers *curmailers = mailers, **last;
9203 struct mailer *m, *mb;
9204
9205 /* Remove all mailers sections which don't have a valid listener.
9206 * This can happen when a mailers section is never referenced.
9207 */
9208 last = &mailers;
9209 while (*last) {
9210 curmailers = *last;
9211 if (curmailers->users) {
9212 last = &curmailers->next;
9213 continue;
9214 }
9215
9216 Warning("Removing incomplete section 'mailers %s'.\n",
9217 curmailers->id);
9218
9219 m = curmailers->mailer_list;
9220 while (m) {
9221 mb = m->next;
9222 free(m->id);
9223 free(m);
9224 m = mb;
9225 }
9226
9227 /* Destroy and unlink this curmailers section.
9228 * Note: curmailers is backed up into *last.
9229 */
9230 free(curmailers->id);
9231 curmailers = curmailers->next;
9232 free(*last);
9233 *last = curmailers;
9234 }
9235 }
9236
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009237 /* Update server_state_file_name to backend name if backend is supposed to use
9238 * a server-state file locally defined and none has been provided */
9239 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9240 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9241 curproxy->server_state_file_name == NULL)
9242 curproxy->server_state_file_name = strdup(curproxy->id);
9243 }
9244
Willy Tarreau34eb6712011-10-24 18:15:04 +02009245 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009246 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009247 MEM_F_SHARED);
9248
William Lallemand48b4bb42017-10-23 14:36:34 +02009249 list_for_each_entry(postparser, &postparsers, list) {
9250 if (postparser->func)
9251 cfgerr += postparser->func();
9252 }
9253
Willy Tarreaubb925012009-07-23 13:36:36 +02009254 if (cfgerr > 0)
9255 err_code |= ERR_ALERT | ERR_FATAL;
9256 out:
9257 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009258}
9259
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009260/*
9261 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9262 * parsing sessions.
9263 */
9264void cfg_register_keywords(struct cfg_kw_list *kwl)
9265{
9266 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9267}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009268
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009269/*
9270 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9271 */
9272void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9273{
9274 LIST_DEL(&kwl->list);
9275 LIST_INIT(&kwl->list);
9276}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009277
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009278/* this function register new section in the haproxy configuration file.
9279 * <section_name> is the name of this new section and <section_parser>
9280 * is the called parser. If two section declaration have the same name,
9281 * only the first declared is used.
9282 */
9283int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009284 int (*section_parser)(const char *, int, char **, int),
9285 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009286{
9287 struct cfg_section *cs;
9288
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009289 list_for_each_entry(cs, &sections, list) {
9290 if (strcmp(cs->section_name, section_name) == 0) {
9291 Alert("register section '%s': already registered.\n", section_name);
9292 return 0;
9293 }
9294 }
9295
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009296 cs = calloc(1, sizeof(*cs));
9297 if (!cs) {
9298 Alert("register section '%s': out of memory.\n", section_name);
9299 return 0;
9300 }
9301
9302 cs->section_name = section_name;
9303 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009304 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009305
9306 LIST_ADDQ(&sections, &cs->list);
9307
9308 return 1;
9309}
9310
William Lallemand48b4bb42017-10-23 14:36:34 +02009311/* this function register a new function which will be called once the haproxy
9312 * configuration file has been parsed. It's useful to check dependencies
9313 * between sections or to resolve items once everything is parsed.
9314 */
9315int cfg_register_postparser(char *name, int (*func)())
9316{
9317 struct cfg_postparser *cp;
9318
9319 cp = calloc(1, sizeof(*cp));
9320 if (!cp) {
9321 Alert("register postparser '%s': out of memory.\n", name);
9322 return 0;
9323 }
9324 cp->name = name;
9325 cp->func = func;
9326
9327 LIST_ADDQ(&postparsers, &cp->list);
9328
9329 return 1;
9330}
9331
Willy Tarreaubaaee002006-06-26 02:48:02 +02009332/*
David Carlier845efb52015-09-25 11:49:18 +01009333 * free all config section entries
9334 */
9335void cfg_unregister_sections(void)
9336{
9337 struct cfg_section *cs, *ics;
9338
9339 list_for_each_entry_safe(cs, ics, &sections, list) {
9340 LIST_DEL(&cs->list);
9341 free(cs);
9342 }
9343}
9344
Christopher Faulet7110b402016-10-26 11:09:44 +02009345void cfg_backup_sections(struct list *backup_sections)
9346{
9347 struct cfg_section *cs, *ics;
9348
9349 list_for_each_entry_safe(cs, ics, &sections, list) {
9350 LIST_DEL(&cs->list);
9351 LIST_ADDQ(backup_sections, &cs->list);
9352 }
9353}
9354
9355void cfg_restore_sections(struct list *backup_sections)
9356{
9357 struct cfg_section *cs, *ics;
9358
9359 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9360 LIST_DEL(&cs->list);
9361 LIST_ADDQ(&sections, &cs->list);
9362 }
9363}
9364
Willy Tarreau659fbf02016-05-26 17:55:28 +02009365__attribute__((constructor))
9366static void cfgparse_init(void)
9367{
9368 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009369 cfg_register_section("listen", cfg_parse_listen, NULL);
9370 cfg_register_section("frontend", cfg_parse_listen, NULL);
9371 cfg_register_section("backend", cfg_parse_listen, NULL);
9372 cfg_register_section("defaults", cfg_parse_listen, NULL);
9373 cfg_register_section("global", cfg_parse_global, NULL);
9374 cfg_register_section("userlist", cfg_parse_users, NULL);
9375 cfg_register_section("peers", cfg_parse_peers, NULL);
9376 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9377 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9378 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009379}
9380
David Carlier845efb52015-09-25 11:49:18 +01009381/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009382 * Local variables:
9383 * c-indent-level: 8
9384 * c-basic-offset: 8
9385 * End:
9386 */