blob: 57f25fac79f52cebbca85cea21695ede020aa14f [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Emeric Brunc60def82017-09-27 14:59:38 +020045#include <common/hathreads.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046
47#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020048#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020049#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010051#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020052#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090053#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020054#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010055#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056
Willy Tarreaueb0c6142007-05-07 00:53:22 +020057#include <proto/acl.h>
Christopher Faulet4fce0d82017-09-18 11:57:31 +020058#include <proto/action.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010059#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020061#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020063#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020064#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010065#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020066#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020067#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020068#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020069#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010070#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020071#include <proto/lb_fwlc.h>
72#include <proto/lb_fwrr.h>
73#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020075#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020076#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
William Lallemandd2ff56d2017-10-16 11:06:50 +0200131 int (*post_section_parser)();
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
William Lallemand48b4bb42017-10-23 14:36:34 +0200139/* store post configuration parsing */
140
141struct cfg_postparser {
142 struct list list;
143 char *name;
144 int (*func)();
145};
146
147struct list postparsers = LIST_HEAD_INIT(postparsers);
148
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100151 const char *name;
152 unsigned int val;
153 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100154 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100156};
157
158/* proxy->options */
159static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100160{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
162 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
163 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
165 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
166 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200168 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200169 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100170 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
172 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
173 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100175#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100179#endif
180
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100182};
183
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184/* proxy->options2 */
185static const struct cfg_opt cfg_opts2[] =
186{
187#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
189 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
190 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100191#else
192 { "splice-request", 0, 0, 0, 0 },
193 { "splice-response", 0, 0, 0, 0 },
194 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
197 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
198 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
199 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
200 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
201 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
202 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
203 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
204 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400205 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100206 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200207 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200208 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100209 { NULL, 0, 0, 0 }
210};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Willy Tarreau6daf3432008-01-22 16:44:08 +0100212static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
214int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100215int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100216char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200218/* List head of all known configuration keywords */
219static struct cfg_kw_list cfg_keywords = {
220 .list = LIST_HEAD_INIT(cfg_keywords.list)
221};
222
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223/*
224 * converts <str> to a list of listeners which are dynamically allocated.
225 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
226 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
227 * - <port> is a numerical port from 1 to 65535 ;
228 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
229 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200230 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
231 * not NULL, it must be a valid pointer to either NULL or a freeable area that
232 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200234int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235{
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 int port, end;
238
239 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200240
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 while (next && *next) {
William Lallemand75ea0a02017-11-15 19:02:58 +0100242 int inherited = 0;
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200243 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
246 str = next;
247 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100248 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249 *next++ = 0;
250 }
251
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100252 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200253 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200254 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100255 if (!ss2)
256 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100258 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100259 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200260 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100264 if (!port || !end) {
265 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
266 goto fail;
267 }
268
Emeric Bruned760922010-10-22 17:59:25 +0200269 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200270 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200271 goto fail;
272 }
273
274 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200275 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200276 goto fail;
277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100279 else if (ss2->ss_family == AF_UNSPEC) {
280 socklen_t addr_len;
William Lallemand75ea0a02017-11-15 19:02:58 +0100281 inherited = 1;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282
283 /* We want to attach to an already bound fd whose number
284 * is in the addr part of ss2 when cast to sockaddr_in.
285 * Note that by definition there is a single listener.
286 * We still have to determine the address family to
287 * register the correct protocol.
288 */
289 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
290 addr_len = sizeof(*ss2);
291 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
292 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
293 goto fail;
294 }
295
296 port = end = get_host_port(ss2);
297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100299 /* OK the address looks correct */
William Lallemand75ea0a02017-11-15 19:02:58 +0100300 if (!create_listeners(bind_conf, ss2, port, end, fd, inherited, err)) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200301 memprintf(err, "%s for address '%s'.\n", *err, str);
302 goto fail;
303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 } /* end while(next) */
305 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200306 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307 fail:
308 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310}
311
William Lallemand6e62fb62015-04-28 16:55:23 +0200312/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100313 * Report an error in <msg> when there are too many arguments. This version is
314 * intended to be used by keyword parsers so that the message will be included
315 * into the general error message. The index is the current keyword in args.
316 * Return 0 if the number of argument is correct, otherwise build a message and
317 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
318 * message may also be null, it will simply not be produced (useful to check only).
319 * <msg> and <err_code> are only affected on error.
320 */
321int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
322{
323 int i;
324
325 if (!*args[index + maxarg + 1])
326 return 0;
327
328 if (msg) {
329 *msg = NULL;
330 memprintf(msg, "%s", args[0]);
331 for (i = 1; i <= index; i++)
332 memprintf(msg, "%s %s", *msg, args[i]);
333
334 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
335 }
336 if (err_code)
337 *err_code |= ERR_ALERT | ERR_FATAL;
338
339 return 1;
340}
341
342/*
343 * same as too_many_args_idx with a 0 index
344 */
345int too_many_args(int maxarg, char **args, char **msg, int *err_code)
346{
347 return too_many_args_idx(maxarg, 0, args, msg, err_code);
348}
349
350/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200351 * Report a fatal Alert when there is too much arguments
352 * The index is the current keyword in args
353 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
354 * Fill err_code with an ERR_ALERT and an ERR_FATAL
355 */
356int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
357{
358 char *kw = NULL;
359 int i;
360
361 if (!*args[index + maxarg + 1])
362 return 0;
363
364 memprintf(&kw, "%s", args[0]);
365 for (i = 1; i <= index; i++) {
366 memprintf(&kw, "%s %s", kw, args[i]);
367 }
368
369 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
370 free(kw);
371 *err_code |= ERR_ALERT | ERR_FATAL;
372 return 1;
373}
374
375/*
376 * same as alertif_too_many_args_idx with a 0 index
377 */
378int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
379{
380 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
381}
382
Willy Tarreau620408f2016-10-21 16:37:51 +0200383/* Report a warning if a rule is placed after a 'tcp-request session' rule.
384 * Return 1 if the warning has been emitted, otherwise 0.
385 */
386int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
387{
388 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
389 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
390 file, line, arg);
391 return 1;
392 }
393 return 0;
394}
395
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200396/* Report a warning if a rule is placed after a 'tcp-request content' rule.
397 * Return 1 if the warning has been emitted, otherwise 0.
398 */
399int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
400{
401 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
402 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
403 file, line, arg);
404 return 1;
405 }
406 return 0;
407}
408
Willy Tarreau61d18892009-03-31 10:49:21 +0200409/* Report a warning if a rule is placed after a 'block' rule.
410 * Return 1 if the warning has been emitted, otherwise 0.
411 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200414 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
416 file, line, arg);
417 return 1;
418 }
419 return 0;
420}
421
Willy Tarreau5002f572014-04-23 01:32:02 +0200422/* Report a warning if a rule is placed after an 'http_request' rule.
423 * Return 1 if the warning has been emitted, otherwise 0.
424 */
425int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
426{
427 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
428 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
429 file, line, arg);
430 return 1;
431 }
432 return 0;
433}
434
Willy Tarreau61d18892009-03-31 10:49:21 +0200435/* Report a warning if a rule is placed after a reqrewrite rule.
436 * Return 1 if the warning has been emitted, otherwise 0.
437 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100438int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200439{
440 if (proxy->req_exp) {
441 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
442 file, line, arg);
443 return 1;
444 }
445 return 0;
446}
447
448/* Report a warning if a rule is placed after a reqadd rule.
449 * Return 1 if the warning has been emitted, otherwise 0.
450 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100453 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200454 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
455 file, line, arg);
456 return 1;
457 }
458 return 0;
459}
460
461/* Report a warning if a rule is placed after a redirect rule.
462 * Return 1 if the warning has been emitted, otherwise 0.
463 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100464int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200465{
466 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
467 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
468 file, line, arg);
469 return 1;
470 }
471 return 0;
472}
473
474/* Report a warning if a rule is placed after a 'use_backend' rule.
475 * Return 1 if the warning has been emitted, otherwise 0.
476 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100477int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200478{
479 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
480 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
481 file, line, arg);
482 return 1;
483 }
484 return 0;
485}
486
Willy Tarreauee445d92014-04-23 01:39:04 +0200487/* Report a warning if a rule is placed after a 'use-server' rule.
488 * Return 1 if the warning has been emitted, otherwise 0.
489 */
490int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
491{
492 if (!LIST_ISEMPTY(&proxy->server_rules)) {
493 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
494 file, line, arg);
495 return 1;
496 }
497 return 0;
498}
499
Willy Tarreaud39ad442016-11-25 15:16:12 +0100500/* report a warning if a redirect rule is dangerously placed */
501int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200502{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100503 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200504 warnif_rule_after_use_server(proxy, file, line, arg);
505}
506
Willy Tarreaud39ad442016-11-25 15:16:12 +0100507/* report a warning if a reqadd rule is dangerously placed */
508int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200509{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100510 return warnif_rule_after_redirect(proxy, file, line, arg) ||
511 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200512}
513
Willy Tarreaud39ad442016-11-25 15:16:12 +0100514/* report a warning if a reqxxx rule is dangerously placed */
515int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200516{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100517 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
518 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200519}
520
521/* report a warning if an http-request rule is dangerously placed */
522int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
523{
Willy Tarreau61d18892009-03-31 10:49:21 +0200524 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200526}
527
Willy Tarreaud39ad442016-11-25 15:16:12 +0100528/* report a warning if a block rule is dangerously placed */
529int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200530{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100531 return warnif_rule_after_http_req(proxy, file, line, arg) ||
532 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaud39ad442016-11-25 15:16:12 +0100535/* report a warning if a "tcp request content" rule is dangerously placed */
536int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200537{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100538 return warnif_rule_after_block(proxy, file, line, arg) ||
539 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200540}
541
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542/* report a warning if a "tcp request session" rule is dangerously placed */
543int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200544{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100545 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
546 warnif_misplaced_tcp_cont(proxy, file, line, arg);
547}
548
549/* report a warning if a "tcp request connection" rule is dangerously placed */
550int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
551{
552 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
553 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200554}
555
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556/* Report it if a request ACL condition uses some keywords that are incompatible
557 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
558 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
559 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100560 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100562{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100563 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567 return 0;
568
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100569 acl = acl_cond_conflicts(cond, where);
570 if (acl) {
571 if (acl->name && *acl->name)
572 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
573 file, line, acl->name, sample_ckp_names(where));
574 else
575 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200576 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100577 return ERR_WARN;
578 }
579 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100580 return 0;
581
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 if (acl->name && *acl->name)
583 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200584 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100585 else
586 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200587 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100588 return ERR_WARN;
589}
590
Christopher Faulet62519022017-10-16 15:49:32 +0200591/* Parse a string representing a process number or a set of processes. It must
592 * be "all", "odd", "even" or a number between 1 and <LONGBITS>. It returns a
593 * mask where bits are set for corresponding processes or 0 if an error occured.
594 *
595 * Note: this function can also be used to parse a thread number or a set of
596 * threads.
597 */
598static unsigned long parse_process_number(const char *arg)
599{
600 unsigned long proc = 0;
601
602 if (strcmp(arg, "all") == 0)
603 proc = ~0UL;
604 else if (strcmp(arg, "odd") == 0)
605 proc = ~0UL/3UL; /* 0x555....555 */
606 else if (strcmp(arg, "even") == 0)
607 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
608 else {
609 proc = atol(arg);
610 if (proc >= 1 && proc <= LONGBITS)
611 proc = 1UL << (proc - 1);
612 }
613 return proc;
614}
615
616/* Parse cpu sets. Each CPU set is either a unique number between 0 and
617 * <LONGBITS> or a range with two such numbers delimited by a dash
618 * ('-'). Multiple CPU numbers or ranges may be specified. On success, it
619 * returns 0. otherwise it returns 1 with an error message in <err>.
620 */
621static unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
622{
623 int cur_arg = 0;
624
625 *cpu_set = 0;
626 while (*args[cur_arg]) {
627 char *dash;
628 unsigned int low, high;
629
630 if (!isdigit((int)*args[cur_arg])) {
631 memprintf(err, "'%s' is not a CPU range.\n", args[cur_arg]);
632 return -1;
633 }
634
635 low = high = str2uic(args[cur_arg]);
636 if ((dash = strchr(args[cur_arg], '-')) != NULL)
637 high = str2uic(dash + 1);
638
639 if (high < low) {
640 unsigned int swap = low;
641 low = high;
642 high = swap;
643 }
644
645 if (high >= LONGBITS) {
646 memprintf(err, "supports CPU numbers from 0 to %d.\n", LONGBITS - 1);
647 return 1;
648 }
649
650 while (low <= high)
651 *cpu_set |= 1UL << low++;
652
653 cur_arg++;
654 }
655 return 0;
656}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 * parse a line in a <global> section. Returns the error code, 0 if OK, or
659 * any combination of :
660 * - ERR_ABORT: must abort ASAP
661 * - ERR_FATAL: we can continue parsing but not start the service
662 * - ERR_WARN: a warning has been emitted
663 * - ERR_ALERT: an alert has been emitted
664 * Only the two first ones can stop processing, the two others are just
665 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200667int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668{
Willy Tarreau058e9072009-07-20 09:30:05 +0200669 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200670 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671
672 if (!strcmp(args[0], "global")) { /* new section */
673 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200674 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 }
677 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200678 if (alertif_too_many_args(0, file, linenum, args, &err_code))
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 global.mode |= MODE_DAEMON;
681 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200682 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200684 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200685 if (*args[1]) {
686 if (!strcmp(args[1], "exit-on-failure")) {
687 global.tune.options |= GTUNE_EXIT_ONFAILURE;
688 } else {
689 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
690 err_code |= ERR_ALERT | ERR_FATAL;
691 goto out;
692 }
693 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200694 global.mode |= MODE_MWORKER;
695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200697 if (alertif_too_many_args(0, file, linenum, args, &err_code))
698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 global.mode |= MODE_DEBUG;
700 }
701 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200702 if (alertif_too_many_args(0, file, linenum, args, &err_code))
703 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100704 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200706 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200707 if (alertif_too_many_args(0, file, linenum, args, &err_code))
708 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100709 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200712 if (alertif_too_many_args(0, file, linenum, args, &err_code))
713 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100714 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100716 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(0, file, linenum, args, &err_code))
718 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100719 global.tune.options &= ~GTUNE_USE_SPLICE;
720 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200721 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200722 if (alertif_too_many_args(0, file, linenum, args, &err_code))
723 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200724 global.tune.options &= ~GTUNE_USE_GAI;
725 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000726 else if (!strcmp(args[0], "noreuseport")) {
727 if (alertif_too_many_args(0, file, linenum, args, &err_code))
728 goto out;
729 global.tune.options &= ~GTUNE_USE_REUSEPORT;
730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200732 if (alertif_too_many_args(0, file, linenum, args, &err_code))
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 global.mode |= MODE_QUIET;
735 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200736 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200737 if (alertif_too_many_args(1, file, linenum, args, &err_code))
738 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200739 if (global.tune.maxpollevents != 0) {
740 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200741 err_code |= ERR_ALERT;
742 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200743 }
744 if (*(args[1]) == 0) {
745 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200748 }
749 global.tune.maxpollevents = atol(args[1]);
750 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100751 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200752 if (alertif_too_many_args(1, file, linenum, args, &err_code))
753 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100754 if (global.tune.maxaccept != 0) {
755 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
757 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100758 }
759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100763 }
764 global.tune.maxaccept = atol(args[1]);
765 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200766 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200767 if (alertif_too_many_args(1, file, linenum, args, &err_code))
768 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200769 if (*(args[1]) == 0) {
770 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
773 }
774 global.tune.chksize = atol(args[1]);
775 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100776 else if (!strcmp(args[0], "tune.recv_enough")) {
777 if (alertif_too_many_args(1, file, linenum, args, &err_code))
778 goto out;
779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
783 }
784 global.tune.recv_enough = atol(args[1]);
785 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100786 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200787 if (alertif_too_many_args(1, file, linenum, args, &err_code))
788 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100789 if (*(args[1]) == 0) {
790 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
793 }
794 global.tune.buf_limit = atol(args[1]);
795 if (global.tune.buf_limit) {
796 if (global.tune.buf_limit < 3)
797 global.tune.buf_limit = 3;
798 if (global.tune.buf_limit <= global.tune.reserved_bufs)
799 global.tune.buf_limit = global.tune.reserved_bufs + 1;
800 }
801 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100802 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200803 if (alertif_too_many_args(1, file, linenum, args, &err_code))
804 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.reserved_bufs = atol(args[1]);
811 if (global.tune.reserved_bufs < 2)
812 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100813 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
814 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100815 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200816 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200817 if (alertif_too_many_args(1, file, linenum, args, &err_code))
818 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200825 if (global.tune.bufsize <= 0) {
826 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200830 }
831 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200832 if (alertif_too_many_args(1, file, linenum, args, &err_code))
833 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200834 if (*(args[1]) == 0) {
835 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT | ERR_FATAL;
837 goto out;
838 }
839 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200840 if (global.tune.maxrewrite < 0) {
841 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
842 err_code |= ERR_ALERT | ERR_FATAL;
843 goto out;
844 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200845 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100846 else if (!strcmp(args[0], "tune.idletimer")) {
847 unsigned int idle;
848 const char *res;
849
William Lallemand1a748ae2015-05-19 16:37:23 +0200850 if (alertif_too_many_args(1, file, linenum, args, &err_code))
851 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857
858 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
859 if (res) {
860 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
861 file, linenum, *res, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 if (idle > 65535) {
867 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870 }
871 global.tune.idle_timer = idle;
872 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100873 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200874 if (alertif_too_many_args(1, file, linenum, args, &err_code))
875 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100876 if (global.tune.client_rcvbuf != 0) {
877 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT;
879 goto out;
880 }
881 if (*(args[1]) == 0) {
882 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886 global.tune.client_rcvbuf = atol(args[1]);
887 }
888 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200889 if (alertif_too_many_args(1, file, linenum, args, &err_code))
890 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100891 if (global.tune.server_rcvbuf != 0) {
892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT;
894 goto out;
895 }
896 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 }
901 global.tune.server_rcvbuf = atol(args[1]);
902 }
903 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200904 if (alertif_too_many_args(1, file, linenum, args, &err_code))
905 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100906 if (global.tune.client_sndbuf != 0) {
907 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT;
909 goto out;
910 }
911 if (*(args[1]) == 0) {
912 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
916 global.tune.client_sndbuf = atol(args[1]);
917 }
918 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200919 if (alertif_too_many_args(1, file, linenum, args, &err_code))
920 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100921 if (global.tune.server_sndbuf != 0) {
922 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
923 err_code |= ERR_ALERT;
924 goto out;
925 }
926 if (*(args[1]) == 0) {
927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 global.tune.server_sndbuf = atol(args[1]);
932 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200933 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200934 if (alertif_too_many_args(1, file, linenum, args, &err_code))
935 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto out;
940 }
941 global.tune.pipesize = atol(args[1]);
942 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100943 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200944 if (alertif_too_many_args(1, file, linenum, args, &err_code))
945 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 global.tune.cookie_len = atol(args[1]) + 1;
952 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200953 else if (!strcmp(args[0], "tune.http.logurilen")) {
954 if (alertif_too_many_args(1, file, linenum, args, &err_code))
955 goto out;
956 if (*(args[1]) == 0) {
957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961 global.tune.requri_len = atol(args[1]) + 1;
962 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200963 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200964 if (alertif_too_many_args(1, file, linenum, args, &err_code))
965 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200971 global.tune.max_http_hdr = atoi(args[1]);
972 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
973 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
974 file, linenum, args[0]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200978 }
William Lallemandf3747832012-11-09 12:33:10 +0100979 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200980 if (alertif_too_many_args(1, file, linenum, args, &err_code))
981 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100982 if (*args[1]) {
983 global.tune.comp_maxlevel = atoi(args[1]);
984 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
985 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
986 file, linenum, args[0]);
987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
989 }
990 } else {
991 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
992 file, linenum, args[0]);
993 err_code |= ERR_ALERT | ERR_FATAL;
994 goto out;
995 }
996 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200997 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
998 if (*args[1]) {
999 global.tune.pattern_cache = atoi(args[1]);
1000 if (global.tune.pattern_cache < 0) {
1001 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1002 file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 } else {
1007 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1008 file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001014 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001017 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT;
1019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001026 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1027 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]);
1028 err_code |= ERR_WARN;
1029 goto out;
1030 }
1031
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 }
1033 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001034 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001037 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001038 err_code |= ERR_ALERT;
1039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 }
1041 if (*(args[1]) == 0) {
1042 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001046 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1047 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]);
1048 err_code |= ERR_WARN;
1049 goto out;
1050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
Simon Horman98637e52014-06-20 12:30:16 +09001052 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001053 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1054 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001055 global.external_check = 1;
1056 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001057 /* user/group name handling */
1058 else if (!strcmp(args[0], "user")) {
1059 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001060 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1061 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001062 if (global.uid != 0) {
1063 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001064 err_code |= ERR_ALERT;
1065 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001066 }
1067 errno = 0;
1068 ha_user = getpwnam(args[1]);
1069 if (ha_user != NULL) {
1070 global.uid = (int)ha_user->pw_uid;
1071 }
1072 else {
1073 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 +02001074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001075 }
1076 }
1077 else if (!strcmp(args[0], "group")) {
1078 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001079 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1080 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001081 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001082 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001083 err_code |= ERR_ALERT;
1084 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001085 }
1086 errno = 0;
1087 ha_group = getgrnam(args[1]);
1088 if (ha_group != NULL) {
1089 global.gid = (int)ha_group->gr_gid;
1090 }
1091 else {
1092 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 +02001093 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001094 }
1095 }
1096 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001098 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 if (*(args[1]) == 0) {
1101 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
1105 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001106 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1107 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1108 file, linenum, args[0], LONGBITS, global.nbproc);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001112 }
Christopher Fauletbe0faa22017-08-29 15:37:10 +02001113 else if (!strcmp(args[0], "nbthread")) {
1114 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1115 goto out;
1116 if (*(args[1]) == 0) {
1117 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1118 err_code |= ERR_ALERT | ERR_FATAL;
1119 goto out;
1120 }
1121 global.nbthread = atol(args[1]);
1122 if (global.nbthread < 1 || global.nbthread > LONGBITS) {
1123 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1124 file, linenum, args[0], LONGBITS, global.nbthread);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128#ifndef USE_THREAD
1129 if (global.nbthread > 1) {
1130 Alert("HAProxy is not compiled with threads support, please check build options for USE_THREAD.\n");
1131 global.nbthread = 1;
1132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
1134 }
1135#endif
1136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001138 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 if (global.maxconn != 0) {
1141 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001142 err_code |= ERR_ALERT;
1143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 }
1145 if (*(args[1]) == 0) {
1146 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT | ERR_FATAL;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
1150 global.maxconn = atol(args[1]);
1151#ifdef SYSTEM_MAXCONN
1152 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1153 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);
1154 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001155 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157#endif /* SYSTEM_MAXCONN */
1158 }
Emeric Brun850efd52014-01-29 12:24:34 +01001159 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001160 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1161 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
1166 }
1167 if (strcmp(args[1],"none") == 0)
1168 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1169 else if (strcmp(args[1],"required") == 0)
1170 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1171 else {
1172 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1173 err_code |= ERR_ALERT | ERR_FATAL;
1174 goto out;
1175 }
1176 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001177 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001178 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1179 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001180 if (global.cps_lim != 0) {
1181 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT;
1183 goto out;
1184 }
1185 if (*(args[1]) == 0) {
1186 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190 global.cps_lim = atol(args[1]);
1191 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001192 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001193 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1194 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001195 if (global.sps_lim != 0) {
1196 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1197 err_code |= ERR_ALERT;
1198 goto out;
1199 }
1200 if (*(args[1]) == 0) {
1201 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1202 err_code |= ERR_ALERT | ERR_FATAL;
1203 goto out;
1204 }
1205 global.sps_lim = atol(args[1]);
1206 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001207 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001208 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1209 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001210 if (global.ssl_lim != 0) {
1211 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1212 err_code |= ERR_ALERT;
1213 goto out;
1214 }
1215 if (*(args[1]) == 0) {
1216 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220 global.ssl_lim = atol(args[1]);
1221 }
William Lallemandd85f9172012-11-09 17:05:39 +01001222 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001223 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1224 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001225 if (*(args[1]) == 0) {
1226 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1227 err_code |= ERR_ALERT | ERR_FATAL;
1228 goto out;
1229 }
1230 global.comp_rate_lim = atoi(args[1]) * 1024;
1231 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001232 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001233 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1234 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001235 if (global.maxpipes != 0) {
1236 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001237 err_code |= ERR_ALERT;
1238 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001239 }
1240 if (*(args[1]) == 0) {
1241 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001244 }
1245 global.maxpipes = atol(args[1]);
1246 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001247 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001248 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1249 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001250 if (*(args[1]) == 0) {
1251 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1252 err_code |= ERR_ALERT | ERR_FATAL;
1253 goto out;
1254 }
William Lallemande3a7d992012-11-20 11:25:20 +01001255 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001256 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001257 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001258 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1259 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001260 if (*(args[1]) == 0) {
1261 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
1264 }
1265 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001266 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001267 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001271 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001272
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001274 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001276 if (global.rlimit_nofile != 0) {
1277 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001278 err_code |= ERR_ALERT;
1279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 }
1281 if (*(args[1]) == 0) {
1282 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285 }
1286 global.rlimit_nofile = atol(args[1]);
1287 }
1288 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001289 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291 if (global.chroot != NULL) {
1292 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001293 err_code |= ERR_ALERT;
1294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001295 }
1296 if (*(args[1]) == 0) {
1297 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 }
1301 global.chroot = strdup(args[1]);
1302 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001303 else if (!strcmp(args[0], "description")) {
1304 int i, len=0;
1305 char *d;
1306
1307 if (!*args[1]) {
1308 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1309 file, linenum, args[0]);
1310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
1312 }
1313
Willy Tarreau348acfe2014-04-14 15:00:39 +02001314 for (i = 1; *args[i]; i++)
1315 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001316
1317 if (global.desc)
1318 free(global.desc);
1319
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001320 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001321
Willy Tarreau348acfe2014-04-14 15:00:39 +02001322 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1323 for (i = 2; *args[i]; i++)
1324 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001325 }
1326 else if (!strcmp(args[0], "node")) {
1327 int i;
1328 char c;
1329
William Lallemand1a748ae2015-05-19 16:37:23 +02001330 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1331 goto out;
1332
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001333 for (i=0; args[1][i]; i++) {
1334 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001335 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1336 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001337 break;
1338 }
1339
1340 if (!i || args[1][i]) {
1341 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1342 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1343 file, linenum, args[0]);
1344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
1346 }
1347
1348 if (global.node)
1349 free(global.node);
1350
1351 global.node = strdup(args[1]);
1352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001354 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 if (global.pidfile != NULL) {
1357 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001358 err_code |= ERR_ALERT;
1359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 }
1361 if (*(args[1]) == 0) {
1362 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
1366 global.pidfile = strdup(args[1]);
1367 }
Emeric Bruned760922010-10-22 17:59:25 +02001368 else if (!strcmp(args[0], "unix-bind")) {
1369 int cur_arg = 1;
1370 while (*(args[cur_arg])) {
1371 if (!strcmp(args[cur_arg], "prefix")) {
1372 if (global.unix_bind.prefix != NULL) {
1373 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1374 err_code |= ERR_ALERT;
1375 cur_arg += 2;
1376 continue;
1377 }
1378
1379 if (*(args[cur_arg+1]) == 0) {
1380 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
1383 }
1384 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1385 cur_arg += 2;
1386 continue;
1387 }
1388
1389 if (!strcmp(args[cur_arg], "mode")) {
1390
1391 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1392 cur_arg += 2;
1393 continue;
1394 }
1395
1396 if (!strcmp(args[cur_arg], "uid")) {
1397
1398 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1399 cur_arg += 2;
1400 continue;
1401 }
1402
1403 if (!strcmp(args[cur_arg], "gid")) {
1404
1405 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1406 cur_arg += 2;
1407 continue;
1408 }
1409
1410 if (!strcmp(args[cur_arg], "user")) {
1411 struct passwd *user;
1412
1413 user = getpwnam(args[cur_arg + 1]);
1414 if (!user) {
1415 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1416 file, linenum, args[0], args[cur_arg + 1 ]);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
1421 global.unix_bind.ux.uid = user->pw_uid;
1422 cur_arg += 2;
1423 continue;
1424 }
1425
1426 if (!strcmp(args[cur_arg], "group")) {
1427 struct group *group;
1428
1429 group = getgrnam(args[cur_arg + 1]);
1430 if (!group) {
1431 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1432 file, linenum, args[0], args[cur_arg + 1 ]);
1433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
1435 }
1436
1437 global.unix_bind.ux.gid = group->gr_gid;
1438 cur_arg += 2;
1439 continue;
1440 }
1441
Willy Tarreaub48f9582011-09-05 01:17:06 +02001442 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001443 file, linenum, args[0]);
1444 err_code |= ERR_ALERT | ERR_FATAL;
1445 goto out;
1446 }
1447 }
William Lallemand0f99e342011-10-12 17:50:54 +02001448 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1449 /* delete previous herited or defined syslog servers */
1450 struct logsrv *back;
1451 struct logsrv *tmp;
1452
1453 if (*(args[1]) != 0) {
1454 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1455 err_code |= ERR_ALERT | ERR_FATAL;
1456 goto out;
1457 }
1458
1459 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1460 LIST_DEL(&tmp->list);
1461 free(tmp);
1462 }
1463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001465 struct sockaddr_storage *sk;
1466 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001467 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001468 int arg = 0;
1469 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001470
William Lallemand1a748ae2015-05-19 16:37:23 +02001471 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1472 goto out;
1473
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 if (*(args[1]) == 0 || *(args[2]) == 0) {
1475 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001476 err_code |= ERR_ALERT | ERR_FATAL;
1477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478 }
William Lallemand0f99e342011-10-12 17:50:54 +02001479
Vincent Bernat02779b62016-04-03 13:48:43 +02001480 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001481
Willy Tarreau18324f52014-06-27 18:10:07 +02001482 /* just after the address, a length may be specified */
1483 if (strcmp(args[arg+2], "len") == 0) {
1484 len = atoi(args[arg+3]);
1485 if (len < 80 || len > 65535) {
1486 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1487 file, linenum, args[arg+3]);
1488 err_code |= ERR_ALERT | ERR_FATAL;
1489 goto out;
1490 }
1491 logsrv->maxlen = len;
1492
1493 /* skip these two args */
1494 arg += 2;
1495 }
1496 else
1497 logsrv->maxlen = MAX_SYSLOG_LEN;
1498
Christopher Faulet084aa962017-08-29 16:54:41 +02001499 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001500 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001501
Dragan Dosen1322d092015-09-22 16:05:32 +02001502 /* after the length, a format may be specified */
1503 if (strcmp(args[arg+2], "format") == 0) {
1504 logsrv->format = get_log_format(args[arg+3]);
1505 if (logsrv->format < 0) {
1506 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1507 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001508 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001509 goto out;
1510 }
1511
1512 /* skip these two args */
1513 arg += 2;
1514 }
1515
David Carlier97880bb2016-04-08 10:35:26 +01001516 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1517 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001518 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001519 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001520
Willy Tarreau18324f52014-06-27 18:10:07 +02001521 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001522 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001523 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001524 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001525 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 }
1527
William Lallemand0f99e342011-10-12 17:50:54 +02001528 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001529 if (*(args[arg+3])) {
1530 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001531 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001532 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001533 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001534 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 }
1536 }
1537
William Lallemand0f99e342011-10-12 17:50:54 +02001538 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001539 if (*(args[arg+4])) {
1540 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001541 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001542 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001544 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001545 }
1546 }
1547
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001548 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001549 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001550 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001551 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001552 free(logsrv);
1553 goto out;
1554 }
1555 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001556
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001557 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001558 if (port1 != port2) {
1559 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1560 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001561 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001562 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001563 goto out;
1564 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001565
William Lallemand0f99e342011-10-12 17:50:54 +02001566 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001567 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001568 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570
William Lallemand0f99e342011-10-12 17:50:54 +02001571 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001572 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001573 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1574 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001575
1576 if (global.log_send_hostname != NULL) {
1577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1578 err_code |= ERR_ALERT;
1579 goto out;
1580 }
1581
1582 if (*(args[1]))
1583 name = args[1];
1584 else
1585 name = hostname;
1586
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001587 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001588 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001589 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001590 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1591 if (global.server_state_base != NULL) {
1592 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1593 err_code |= ERR_ALERT;
1594 goto out;
1595 }
1596
1597 if (!*(args[1])) {
1598 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1599 err_code |= ERR_FATAL;
1600 goto out;
1601 }
1602
1603 global.server_state_base = strdup(args[1]);
1604 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001605 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1606 if (global.server_state_file != NULL) {
1607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1608 err_code |= ERR_ALERT;
1609 goto out;
1610 }
1611
1612 if (!*(args[1])) {
1613 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1614 err_code |= ERR_FATAL;
1615 goto out;
1616 }
1617
1618 global.server_state_file = strdup(args[1]);
1619 }
Kevinm48936af2010-12-22 16:08:21 +00001620 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001621 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1622 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001623 if (*(args[1]) == 0) {
1624 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
1627 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001628 chunk_destroy(&global.log_tag);
1629 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001630 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001631 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001632 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1633 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001634 if (global.spread_checks != 0) {
1635 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001636 err_code |= ERR_ALERT;
1637 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001638 }
1639 if (*(args[1]) == 0) {
1640 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001643 }
1644 global.spread_checks = atol(args[1]);
1645 if (global.spread_checks < 0 || global.spread_checks > 50) {
1646 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001647 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001650 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1651 const char *err;
1652 unsigned int val;
1653
William Lallemand1a748ae2015-05-19 16:37:23 +02001654 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1655 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001656 if (*(args[1]) == 0) {
1657 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
1660 }
1661
1662 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1663 if (err) {
1664 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1665 err_code |= ERR_ALERT | ERR_FATAL;
1666 }
1667 global.max_spread_checks = val;
1668 if (global.max_spread_checks < 0) {
1669 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1670 err_code |= ERR_ALERT | ERR_FATAL;
1671 }
1672 }
Christopher Faulet62519022017-10-16 15:49:32 +02001673 else if (strcmp(args[0], "cpu-map") == 0) {
1674 /* map a process list to a CPU set */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001675#ifdef USE_CPU_AFFINITY
Christopher Faulet62519022017-10-16 15:49:32 +02001676 unsigned long proc, cpus;
1677 int i;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001678
Christopher Faulet62519022017-10-16 15:49:32 +02001679 proc = parse_process_number(args[1]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001680 if (!proc || !*args[2]) {
Christopher Faulet62519022017-10-16 15:49:32 +02001681 Alert("parsing [%s:%d]: %s expects a process number "
1682 " ('all', 'odd', 'even', or a number from 1 to %d), "
1683 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001684 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
1687 }
Christopher Faulet62519022017-10-16 15:49:32 +02001688 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
1689 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001692 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001693 for (i = 0; i < LONGBITS; i++)
1694 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001695 global.cpu_map[i] = cpus;
1696#else
Christopher Faulet62519022017-10-16 15:49:32 +02001697 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1698 file, linenum, args[0]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Christopher Faulet62519022017-10-16 15:49:32 +02001701#endif /* ! USE_CPU_AFFINITY */
1702 }
1703 else if (strcmp(args[0], "thread-map") == 0) {
1704 /* map a thread list to a CPU set */
1705#ifdef USE_CPU_AFFINITY
1706#ifdef USE_THREAD
1707 unsigned long proc, thread, cpus;
1708 int i, j;
1709
1710 proc = parse_process_number(args[1]);
1711 thread = parse_process_number(args[2]);
1712 if (!proc || !thread || !*args[3]) {
1713 Alert("parsing [%s:%d]: %s expects a process number "
1714 "('all', 'odd', 'even', or a number from 1 to %d), "
1715 " followed by a thread number using the same format, "
1716 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
1717 file, linenum, args[0], LONGBITS, LONGBITS - 1);
1718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
1720 }
1721 if (parse_cpu_set((const char **)args+3, &cpus, &errmsg)) {
1722 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726 for (i = 0; i < LONGBITS; i++)
1727 if (proc & (1UL << i)) {
1728 for (j = 0; j < LONGBITS; j++)
1729 if (thread & (1UL << j))
1730 global.thread_map[i][j] = cpus;
1731 }
1732#else
1733 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_THREAD.\n",
1734 file, linenum, args[0]);
1735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
1737#endif /* ! USE_THREAD*/
1738#else
1739 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1740 file, linenum, args[0]);
1741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
1743#endif /* ! USE_CPU_AFFINITY */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001744 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001745 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1746 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1747 goto out;
1748
1749 if (*(args[2]) == 0) {
1750 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1751 err_code |= ERR_ALERT | ERR_FATAL;
1752 goto out;
1753 }
1754
1755 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1756 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1757 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1758 err_code |= ERR_ALERT | ERR_FATAL;
1759 goto out;
1760 }
1761 }
1762 else if (!strcmp(args[0], "unsetenv")) {
1763 int arg;
1764
1765 if (*(args[1]) == 0) {
1766 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
1771 for (arg = 1; *args[arg]; arg++) {
1772 if (unsetenv(args[arg]) != 0) {
1773 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
1776 }
1777 }
1778 }
1779 else if (!strcmp(args[0], "resetenv")) {
1780 extern char **environ;
1781 char **env = environ;
1782
1783 /* args contain variable names to keep, one per argument */
1784 while (*env) {
1785 int arg;
1786
1787 /* look for current variable in among all those we want to keep */
1788 for (arg = 1; *args[arg]; arg++) {
1789 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1790 (*env)[strlen(args[arg])] == '=')
1791 break;
1792 }
1793
1794 /* delete this variable */
1795 if (!*args[arg]) {
1796 char *delim = strchr(*env, '=');
1797
1798 if (!delim || delim - *env >= trash.size) {
1799 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
1802 }
1803
1804 memcpy(trash.str, *env, delim - *env);
1805 trash.str[delim - *env] = 0;
1806
1807 if (unsetenv(trash.str) != 0) {
1808 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
1812 }
1813 else
1814 env++;
1815 }
1816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001818 struct cfg_kw_list *kwl;
1819 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001820 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001821
1822 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1823 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1824 if (kwl->kw[index].section != CFG_GLOBAL)
1825 continue;
1826 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001827 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001828 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001829 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001830 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001831 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001832 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001833 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001834 err_code |= ERR_WARN;
1835 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001836 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001837 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001838 }
1839 }
1840 }
1841
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001843 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001845
Willy Tarreau058e9072009-07-20 09:30:05 +02001846 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001847 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001848 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849}
1850
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001851void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001853 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 defproxy.mode = PR_MODE_TCP;
1855 defproxy.state = PR_STNEW;
1856 defproxy.maxconn = cfg_maxpconn;
1857 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001858 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001859 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001860
Simon Horman66183002013-02-23 10:16:43 +09001861 defproxy.defsrv.check.inter = DEF_CHKINTR;
1862 defproxy.defsrv.check.fastinter = 0;
1863 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001864 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1865 defproxy.defsrv.agent.fastinter = 0;
1866 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001867 defproxy.defsrv.check.rise = DEF_RISETIME;
1868 defproxy.defsrv.check.fall = DEF_FALLTIME;
1869 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1870 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001871 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001872 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001873 defproxy.defsrv.maxqueue = 0;
1874 defproxy.defsrv.minconn = 0;
1875 defproxy.defsrv.maxconn = 0;
1876 defproxy.defsrv.slowstart = 0;
1877 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1878 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1879 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001880
1881 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001882 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883}
1884
Willy Tarreauade5ec42010-01-28 19:33:49 +01001885
Willy Tarreau63af98d2014-05-18 08:11:41 +02001886/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1887 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1888 * ERR_FATAL in case of error.
1889 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001890static int create_cond_regex_rule(const char *file, int line,
1891 struct proxy *px, int dir, int action, int flags,
1892 const char *cmd, const char *reg, const char *repl,
1893 const char **cond_start)
1894{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001895 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001896 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001898 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001899 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001900 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001901 int cs;
1902 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001903
1904 if (px == &defproxy) {
1905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001906 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001907 goto err;
1908 }
1909
1910 if (*reg == 0) {
1911 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001912 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001913 goto err;
1914 }
1915
Christopher Faulet898566e2016-10-26 11:06:28 +02001916 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001917 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001918
Willy Tarreau5321c422010-01-28 20:35:13 +01001919 if (cond_start &&
1920 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02001921 if ((cond = build_acl_cond(file, line, &px->acl, px, cond_start, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001922 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1923 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001924 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001925 goto err;
1926 }
1927 }
1928 else if (cond_start && **cond_start) {
1929 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1930 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001931 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001932 goto err;
1933 }
1934
Willy Tarreau63af98d2014-05-18 08:11:41 +02001935 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001936 (dir == SMP_OPT_DIR_REQ) ?
1937 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1938 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1939 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001940
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001941 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001942 if (!preg) {
1943 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001944 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001945 goto err;
1946 }
1947
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001948 cs = !(flags & REG_ICASE);
1949 cap = !(flags & REG_NOSUB);
1950 error = NULL;
1951 if (!regex_comp(reg, preg, cs, cap, &error)) {
1952 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1953 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001954 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001955 goto err;
1956 }
1957
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001958 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001959 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001960 if (repl && err) {
1961 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1962 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001963 ret_code |= ERR_ALERT | ERR_FATAL;
1964 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001965 }
1966
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001967 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001968 ret_code |= ERR_WARN;
1969
1970 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001971
Willy Tarreau63af98d2014-05-18 08:11:41 +02001972 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001973 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001974 err:
1975 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001976 free(errmsg);
1977 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001978}
1979
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980/*
William Lallemand51097192015-04-14 16:35:22 +02001981 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001982 * Returns the error code, 0 if OK, or any combination of :
1983 * - ERR_ABORT: must abort ASAP
1984 * - ERR_FATAL: we can continue parsing but not start the service
1985 * - ERR_WARN: a warning has been emitted
1986 * - ERR_ALERT: an alert has been emitted
1987 * Only the two first ones can stop processing, the two others are just
1988 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001990int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1991{
1992 static struct peers *curpeers = NULL;
1993 struct peer *newpeer = NULL;
1994 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001995 struct bind_conf *bind_conf;
1996 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001997 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001998 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001999
2000 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002001 if (!*args[1]) {
2002 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002003 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002004 goto out;
2005 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002006
William Lallemand6e62fb62015-04-28 16:55:23 +02002007 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2008 goto out;
2009
Emeric Brun32da3c42010-09-23 18:39:19 +02002010 err = invalid_char(args[1]);
2011 if (err) {
2012 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2013 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002014 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002015 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002016 }
2017
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002018 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002019 /*
2020 * If there are two proxies with the same name only following
2021 * combinations are allowed:
2022 */
2023 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002024 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 +02002025 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002026 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002027 }
2028 }
2029
Vincent Bernat02779b62016-04-03 13:48:43 +02002030 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2032 err_code |= ERR_ALERT | ERR_ABORT;
2033 goto out;
2034 }
2035
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002036 curpeers->next = cfg_peers;
2037 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002038 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002039 curpeers->conf.line = linenum;
2040 curpeers->last_change = now.tv_sec;
2041 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002042 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002043 }
2044 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002045 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002046 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002047 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002048
2049 if (!*args[2]) {
2050 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2051 file, linenum, args[0]);
2052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
2054 }
2055
2056 err = invalid_char(args[1]);
2057 if (err) {
2058 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2059 file, linenum, *err, args[1]);
2060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
2062 }
2063
Vincent Bernat02779b62016-04-03 13:48:43 +02002064 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002065 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2066 err_code |= ERR_ALERT | ERR_ABORT;
2067 goto out;
2068 }
2069
2070 /* the peers are linked backwards first */
2071 curpeers->count++;
2072 newpeer->next = curpeers->remote;
2073 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002074 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002075 newpeer->conf.line = linenum;
2076
2077 newpeer->last_change = now.tv_sec;
2078 newpeer->id = strdup(args[1]);
2079
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002080 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002081 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002082 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002085 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002086
2087 proto = protocol_by_family(sk->ss_family);
2088 if (!proto || !proto->connect) {
2089 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2090 file, linenum, args[0], args[1]);
2091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
2093 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002094
2095 if (port1 != port2) {
2096 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2097 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
2100 }
2101
Willy Tarreau2aa38802013-02-20 19:20:59 +01002102 if (!port1) {
2103 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2104 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
2107 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002108
Emeric Brun32da3c42010-09-23 18:39:19 +02002109 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002110 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002111 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002112 newpeer->sock_init_arg = NULL;
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002113 HA_SPIN_INIT(&newpeer->lock);
Willy Tarreau26d8c592012-05-07 18:12:14 +02002114
Emeric Brun32da3c42010-09-23 18:39:19 +02002115 if (strcmp(newpeer->id, localpeer) == 0) {
2116 /* Current is local peer, it define a frontend */
2117 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002118 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002119
2120 if (!curpeers->peers_fe) {
2121 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2122 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2123 err_code |= ERR_ALERT | ERR_ABORT;
2124 goto out;
2125 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002126
Willy Tarreau237250c2011-07-29 01:49:03 +02002127 init_new_proxy(curpeers->peers_fe);
2128 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002129 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002130 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2131 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002132 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002133
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002134 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002135
Willy Tarreau902636f2013-03-10 19:44:48 +01002136 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2137 if (errmsg && *errmsg) {
2138 indent_msg(&errmsg, 2);
2139 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002140 }
2141 else
2142 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2143 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002144 err_code |= ERR_FATAL;
2145 goto out;
2146 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002147
2148 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002149 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002150 l->maxconn = curpeers->peers_fe->maxconn;
2151 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002152 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002153 l->analysers |= curpeers->peers_fe->fe_req_ana;
2154 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002155 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2156 global.maxsock += l->maxconn;
2157 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002159 else {
2160 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2161 file, linenum, args[0], args[1],
2162 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2163 err_code |= ERR_FATAL;
2164 goto out;
2165 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002166 }
2167 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002168 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2169 curpeers->state = PR_STSTOPPED;
2170 }
2171 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2172 curpeers->state = PR_STNEW;
2173 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002174 else if (*args[0] != 0) {
2175 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179
2180out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002181 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002182 return err_code;
2183}
2184
Baptiste Assmann325137d2015-04-13 23:40:55 +02002185/*
2186 * Parse a <resolvers> section.
2187 * Returns the error code, 0 if OK, or any combination of :
2188 * - ERR_ABORT: must abort ASAP
2189 * - ERR_FATAL: we can continue parsing but not start the service
2190 * - ERR_WARN: a warning has been emitted
2191 * - ERR_ALERT: an alert has been emitted
2192 * Only the two first ones can stop processing, the two others are just
2193 * indicators.
2194 */
2195int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2196{
2197 static struct dns_resolvers *curr_resolvers = NULL;
2198 struct dns_nameserver *newnameserver = NULL;
2199 const char *err;
2200 int err_code = 0;
2201 char *errmsg = NULL;
2202
2203 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2204 if (!*args[1]) {
2205 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2206 err_code |= ERR_ALERT | ERR_ABORT;
2207 goto out;
2208 }
2209
2210 err = invalid_char(args[1]);
2211 if (err) {
2212 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2213 file, linenum, *err, args[0], args[1]);
2214 err_code |= ERR_ALERT | ERR_ABORT;
2215 goto out;
2216 }
2217
2218 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2219 /* Error if two resolvers owns the same name */
2220 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2221 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2222 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2223 err_code |= ERR_ALERT | ERR_ABORT;
2224 }
2225 }
2226
Vincent Bernat02779b62016-04-03 13:48:43 +02002227 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002228 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2229 err_code |= ERR_ALERT | ERR_ABORT;
2230 goto out;
2231 }
2232
2233 /* default values */
2234 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2235 curr_resolvers->conf.file = strdup(file);
2236 curr_resolvers->conf.line = linenum;
2237 curr_resolvers->id = strdup(args[1]);
2238 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002239 /* default maximum response size */
2240 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002241 /* default hold period for nx, other, refuse and timeout is 30s */
2242 curr_resolvers->hold.nx = 30000;
2243 curr_resolvers->hold.other = 30000;
2244 curr_resolvers->hold.refused = 30000;
2245 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002246 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002247 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002248 curr_resolvers->hold.valid = 10000;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002249 curr_resolvers->timeout.resolve = 1000;
2250 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002251 curr_resolvers->resolve_retries = 3;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002252 curr_resolvers->nb_nameservers = 0;
2253 LIST_INIT(&curr_resolvers->nameservers);
2254 LIST_INIT(&curr_resolvers->resolutions.curr);
2255 LIST_INIT(&curr_resolvers->resolutions.wait);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002256 HA_SPIN_INIT(&curr_resolvers->lock);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002257 }
2258 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2259 struct sockaddr_storage *sk;
2260 int port1, port2;
2261 struct protocol *proto;
2262
2263 if (!*args[2]) {
2264 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2265 file, linenum, args[0]);
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
2268 }
2269
2270 err = invalid_char(args[1]);
2271 if (err) {
2272 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2273 file, linenum, *err, args[1]);
2274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
2276 }
2277
Christopher Faulet67957bd2017-09-27 11:00:59 +02002278 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002279 /* Error if two resolvers owns the same name */
2280 if (strcmp(newnameserver->id, args[1]) == 0) {
2281 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2282 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2283 err_code |= ERR_ALERT | ERR_FATAL;
2284 }
2285 }
2286
Vincent Bernat02779b62016-04-03 13:48:43 +02002287 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002288 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2289 err_code |= ERR_ALERT | ERR_ABORT;
2290 goto out;
2291 }
2292
2293 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002294 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002295 newnameserver->resolvers = curr_resolvers;
2296 newnameserver->conf.file = strdup(file);
2297 newnameserver->conf.line = linenum;
2298 newnameserver->id = strdup(args[1]);
2299
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002300 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002301 if (!sk) {
2302 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306
2307 proto = protocol_by_family(sk->ss_family);
2308 if (!proto || !proto->connect) {
2309 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2310 file, linenum, args[0], args[1]);
2311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
2313 }
2314
2315 if (port1 != port2) {
2316 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2317 file, linenum, args[0], args[1], args[2]);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002322 if (!port1 && !port2) {
2323 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2324 file, linenum, args[0], args[1]);
2325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
2327 }
2328
Baptiste Assmann325137d2015-04-13 23:40:55 +02002329 newnameserver->addr = *sk;
2330 }
2331 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2332 const char *res;
2333 unsigned int time;
2334
2335 if (!*args[2]) {
2336 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2337 file, linenum, args[0]);
2338 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2343 if (res) {
2344 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2345 file, linenum, *res, args[0]);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002349 if (strcmp(args[1], "nx") == 0)
2350 curr_resolvers->hold.nx = time;
2351 else if (strcmp(args[1], "other") == 0)
2352 curr_resolvers->hold.other = time;
2353 else if (strcmp(args[1], "refused") == 0)
2354 curr_resolvers->hold.refused = time;
2355 else if (strcmp(args[1], "timeout") == 0)
2356 curr_resolvers->hold.timeout = time;
2357 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002358 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002359 else if (strcmp(args[1], "obsolete") == 0)
2360 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002361 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002362 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002363 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
2366 }
2367
2368 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002369 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002370 int i = 0;
2371
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002372 if (!*args[1]) {
2373 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2374 file, linenum, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002378
2379 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002380 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2381 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2382 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
2385 }
2386
2387 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002388 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002389 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002390 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2391 file, linenum, args[0]);
2392 err_code |= ERR_WARN;
2393 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002394 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002395 else if (strcmp(args[0], "resolve_retries") == 0) {
2396 if (!*args[1]) {
2397 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2398 file, linenum, args[0]);
2399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
2401 }
2402 curr_resolvers->resolve_retries = atoi(args[1]);
2403 }
2404 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002405 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002406 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002407 file, linenum, args[0]);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002411 else if (strcmp(args[1], "retry") == 0 ||
2412 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002413 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002414 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002415
2416 if (!*args[2]) {
2417 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2418 file, linenum, args[0], args[1]);
2419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
2421 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002422 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002423 if (res) {
2424 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2425 file, linenum, *res, args[0], args[1]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002429 if (args[1][2] == 't')
2430 curr_resolvers->timeout.retry = tout;
2431 else
2432 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002433 }
2434 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002435 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002436 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
2439 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002440 } /* neither "nameserver" nor "resolvers" */
2441 else if (*args[0] != 0) {
2442 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446
2447 out:
2448 free(errmsg);
2449 return err_code;
2450}
Simon Horman0d16a402015-01-30 11:22:58 +09002451
2452/*
William Lallemand51097192015-04-14 16:35:22 +02002453 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002454 * Returns the error code, 0 if OK, or any combination of :
2455 * - ERR_ABORT: must abort ASAP
2456 * - ERR_FATAL: we can continue parsing but not start the service
2457 * - ERR_WARN: a warning has been emitted
2458 * - ERR_ALERT: an alert has been emitted
2459 * Only the two first ones can stop processing, the two others are just
2460 * indicators.
2461 */
2462int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2463{
2464 static struct mailers *curmailers = NULL;
2465 struct mailer *newmailer = NULL;
2466 const char *err;
2467 int err_code = 0;
2468 char *errmsg = NULL;
2469
2470 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2471 if (!*args[1]) {
2472 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2473 err_code |= ERR_ALERT | ERR_ABORT;
2474 goto out;
2475 }
2476
2477 err = invalid_char(args[1]);
2478 if (err) {
2479 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2480 file, linenum, *err, args[0], args[1]);
2481 err_code |= ERR_ALERT | ERR_ABORT;
2482 goto out;
2483 }
2484
2485 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2486 /*
2487 * If there are two proxies with the same name only following
2488 * combinations are allowed:
2489 */
2490 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002491 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 +09002492 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002494 }
2495 }
2496
Vincent Bernat02779b62016-04-03 13:48:43 +02002497 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002498 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2499 err_code |= ERR_ALERT | ERR_ABORT;
2500 goto out;
2501 }
2502
2503 curmailers->next = mailers;
2504 mailers = curmailers;
2505 curmailers->conf.file = strdup(file);
2506 curmailers->conf.line = linenum;
2507 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002508 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2509 * But need enough time so that timeouts don't occur
2510 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002511 }
2512 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2513 struct sockaddr_storage *sk;
2514 int port1, port2;
2515 struct protocol *proto;
2516
2517 if (!*args[2]) {
2518 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2519 file, linenum, args[0]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523
2524 err = invalid_char(args[1]);
2525 if (err) {
2526 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2527 file, linenum, *err, args[1]);
2528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
2530 }
2531
Vincent Bernat02779b62016-04-03 13:48:43 +02002532 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002533 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2534 err_code |= ERR_ALERT | ERR_ABORT;
2535 goto out;
2536 }
2537
2538 /* the mailers are linked backwards first */
2539 curmailers->count++;
2540 newmailer->next = curmailers->mailer_list;
2541 curmailers->mailer_list = newmailer;
2542 newmailer->mailers = curmailers;
2543 newmailer->conf.file = strdup(file);
2544 newmailer->conf.line = linenum;
2545
2546 newmailer->id = strdup(args[1]);
2547
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002548 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002549 if (!sk) {
2550 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
2553 }
2554
2555 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002556 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2557 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002558 file, linenum, args[0], args[1]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562
2563 if (port1 != port2) {
2564 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2565 file, linenum, args[0], args[1], args[2]);
2566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
2568 }
2569
2570 if (!port1) {
2571 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2572 file, linenum, args[0], args[1], args[2]);
2573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
2575 }
2576
2577 newmailer->addr = *sk;
2578 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002579 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002580 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002581 }
2582 else if (strcmp(args[0], "timeout") == 0) {
2583 if (!*args[1]) {
2584 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2585 file, linenum, args[0]);
2586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
2588 }
2589 else if (strcmp(args[1], "mail") == 0) {
2590 const char *res;
2591 unsigned int timeout_mail;
2592 if (!*args[2]) {
2593 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2594 file, linenum, args[0], args[1]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2599 if (res) {
2600 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2601 file, linenum, *res, args[0]);
2602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
2604 }
2605 if (timeout_mail <= 0) {
2606 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
2609 }
2610 curmailers->timeout.mail = timeout_mail;
2611 } else {
2612 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2613 file, linenum, args[0], args[1]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617 }
Simon Horman0d16a402015-01-30 11:22:58 +09002618 else if (*args[0] != 0) {
2619 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
2622 }
2623
2624out:
2625 free(errmsg);
2626 return err_code;
2627}
2628
Simon Horman9dc49962015-01-30 11:22:59 +09002629static void free_email_alert(struct proxy *p)
2630{
2631 free(p->email_alert.mailers.name);
2632 p->email_alert.mailers.name = NULL;
2633 free(p->email_alert.from);
2634 p->email_alert.from = NULL;
2635 free(p->email_alert.to);
2636 p->email_alert.to = NULL;
2637 free(p->email_alert.myhostname);
2638 p->email_alert.myhostname = NULL;
2639}
2640
Willy Tarreau3842f002009-06-14 11:39:52 +02002641int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642{
2643 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002644 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002645 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002646 int rc;
2647 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002648 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002649 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002650 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002651 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002652 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653
Willy Tarreau977b8e42006-12-29 14:19:17 +01002654 if (!strcmp(args[0], "listen"))
2655 rc = PR_CAP_LISTEN;
2656 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002657 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002658 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002659 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002660 else
2661 rc = PR_CAP_NONE;
2662
2663 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002664 if (!*args[1]) {
2665 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002666 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_ABORT;
2669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002671
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002672 err = invalid_char(args[1]);
2673 if (err) {
2674 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2675 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002677 }
2678
Willy Tarreau8f50b682015-05-26 11:45:02 +02002679 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2680 if (curproxy) {
2681 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2682 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2683 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002684 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002685 }
2686
Vincent Bernat02779b62016-04-03 13:48:43 +02002687 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_ABORT;
2690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002692
Willy Tarreau97cb7802010-01-03 20:23:58 +01002693 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 curproxy->next = proxy;
2695 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002696 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2697 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002698 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002700 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002701 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702
William Lallemand6e62fb62015-04-28 16:55:23 +02002703 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2704 if (curproxy->cap & PR_CAP_FE)
2705 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 }
2708
2709 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002710 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002711 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002712
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002715 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002716 curproxy->no_options = defproxy.no_options;
2717 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002718 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002719 curproxy->except_net = defproxy.except_net;
2720 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002721 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002722 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002724 if (defproxy.fwdfor_hdr_len) {
2725 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2726 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2727 }
2728
Willy Tarreaub86db342009-11-30 11:50:16 +01002729 if (defproxy.orgto_hdr_len) {
2730 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2731 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2732 }
2733
Mark Lamourinec2247f02012-01-04 13:02:01 -05002734 if (defproxy.server_id_hdr_len) {
2735 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2736 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2737 }
2738
Willy Tarreau977b8e42006-12-29 14:19:17 +01002739 if (curproxy->cap & PR_CAP_FE) {
2740 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002741 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002742 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743
2744 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002745 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2746 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002747
2748 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750
Willy Tarreau977b8e42006-12-29 14:19:17 +01002751 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002752 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002753 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002754 curproxy->fullconn = defproxy.fullconn;
2755 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002756 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002757 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002759 if (defproxy.check_req) {
2760 curproxy->check_req = calloc(1, defproxy.check_len);
2761 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2762 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002763 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002765 if (defproxy.expect_str) {
2766 curproxy->expect_str = strdup(defproxy.expect_str);
2767 if (defproxy.expect_regex) {
2768 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002769 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2770 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002771 }
2772 }
2773
Willy Tarreau67402132012-05-31 20:40:20 +02002774 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775 if (defproxy.cookie_name)
2776 curproxy->cookie_name = strdup(defproxy.cookie_name);
2777 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002778
2779 if (defproxy.dyncookie_key)
2780 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002781 if (defproxy.cookie_domain)
2782 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002783
Willy Tarreau31936852010-10-06 16:59:56 +02002784 if (defproxy.cookie_maxidle)
2785 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2786
2787 if (defproxy.cookie_maxlife)
2788 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2789
Emeric Brun647caf12009-06-30 17:57:00 +02002790 if (defproxy.rdp_cookie_name)
2791 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2792 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2793
Willy Tarreau01732802007-11-01 22:48:15 +01002794 if (defproxy.url_param_name)
2795 curproxy->url_param_name = strdup(defproxy.url_param_name);
2796 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002797
Benoitaffb4812009-03-25 13:02:10 +01002798 if (defproxy.hh_name)
2799 curproxy->hh_name = strdup(defproxy.hh_name);
2800 curproxy->hh_len = defproxy.hh_len;
2801 curproxy->hh_match_domain = defproxy.hh_match_domain;
2802
Willy Tarreauef9a3602012-12-08 22:29:20 +01002803 if (defproxy.conn_src.iface_name)
2804 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2805 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002806 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002807#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002808 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002809#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002810 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002812
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002813 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002814 if (defproxy.capture_name)
2815 curproxy->capture_name = strdup(defproxy.capture_name);
2816 curproxy->capture_namelen = defproxy.capture_namelen;
2817 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819
Willy Tarreau977b8e42006-12-29 14:19:17 +01002820 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002821 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002822 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002823 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002824 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002825 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002826 curproxy->mon_net = defproxy.mon_net;
2827 curproxy->mon_mask = defproxy.mon_mask;
2828 if (defproxy.monitor_uri)
2829 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2830 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002831 if (defproxy.defbe.name)
2832 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002833
2834 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002835 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2836 if (curproxy->conf.logformat_string &&
2837 curproxy->conf.logformat_string != default_http_log_format &&
2838 curproxy->conf.logformat_string != default_tcp_log_format &&
2839 curproxy->conf.logformat_string != clf_http_log_format)
2840 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2841
2842 if (defproxy.conf.lfs_file) {
2843 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2844 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2845 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002846
2847 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2848 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2849 if (curproxy->conf.logformat_sd_string &&
2850 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2851 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2852
2853 if (defproxy.conf.lfsd_file) {
2854 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2855 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2856 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002857 }
2858
2859 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002860 curproxy->timeout.connect = defproxy.timeout.connect;
2861 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002862 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002863 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002864 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002865 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002866 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002867 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002868 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002869 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002870 }
2871
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002873 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002874
2875 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002876 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002877 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002878 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002879 LIST_INIT(&node->list);
2880 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2881 }
2882
Willy Tarreau62a61232013-04-12 18:13:46 +02002883 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2884 if (curproxy->conf.uniqueid_format_string)
2885 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2886
Dragan Dosen43885c72015-10-01 13:18:13 +02002887 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002888
Willy Tarreau62a61232013-04-12 18:13:46 +02002889 if (defproxy.conf.uif_file) {
2890 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2891 curproxy->conf.uif_line = defproxy.conf.uif_line;
2892 }
William Lallemanda73203e2012-03-12 12:48:57 +01002893
2894 /* copy default header unique id */
2895 if (defproxy.header_unique_id)
2896 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2897
William Lallemand82fe75c2012-10-23 10:25:10 +02002898 /* default compression options */
2899 if (defproxy.comp != NULL) {
2900 curproxy->comp = calloc(1, sizeof(struct comp));
2901 curproxy->comp->algos = defproxy.comp->algos;
2902 curproxy->comp->types = defproxy.comp->types;
2903 }
2904
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002906 curproxy->conf.used_listener_id = EB_ROOT;
2907 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002908
Simon Horman98637e52014-06-20 12:30:16 +09002909 if (defproxy.check_path)
2910 curproxy->check_path = strdup(defproxy.check_path);
2911 if (defproxy.check_command)
2912 curproxy->check_command = strdup(defproxy.check_command);
2913
Simon Horman9dc49962015-01-30 11:22:59 +09002914 if (defproxy.email_alert.mailers.name)
2915 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2916 if (defproxy.email_alert.from)
2917 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2918 if (defproxy.email_alert.to)
2919 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2920 if (defproxy.email_alert.myhostname)
2921 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002922 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002923 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002924
Willy Tarreau93893792009-07-23 13:19:11 +02002925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 }
2927 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2928 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002929 /* FIXME-20070101: we should do this too at the end of the
2930 * config parsing to free all default values.
2931 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002932 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2933 err_code |= ERR_ABORT;
2934 goto out;
2935 }
2936
Willy Tarreaua534fea2008-08-03 12:19:50 +02002937 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002938 free(defproxy.check_command);
2939 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002940 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002941 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002942 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002943 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002944 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002945 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002946 free(defproxy.capture_name);
2947 free(defproxy.monitor_uri);
2948 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002949 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002950 free(defproxy.fwdfor_hdr_name);
2951 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002952 free(defproxy.orgto_hdr_name);
2953 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002954 free(defproxy.server_id_hdr_name);
2955 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002956 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002957 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002958 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002959 free(defproxy.expect_regex);
2960 defproxy.expect_regex = NULL;
2961 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002962
Willy Tarreau62a61232013-04-12 18:13:46 +02002963 if (defproxy.conf.logformat_string != default_http_log_format &&
2964 defproxy.conf.logformat_string != default_tcp_log_format &&
2965 defproxy.conf.logformat_string != clf_http_log_format)
2966 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002967
Willy Tarreau62a61232013-04-12 18:13:46 +02002968 free(defproxy.conf.uniqueid_format_string);
2969 free(defproxy.conf.lfs_file);
2970 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002971 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002972 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002973
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002974 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2975 free(defproxy.conf.logformat_sd_string);
2976 free(defproxy.conf.lfsd_file);
2977
Willy Tarreaua534fea2008-08-03 12:19:50 +02002978 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002979 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002980
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 /* we cannot free uri_auth because it might already be used */
2982 init_default_instance();
2983 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002984 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2985 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002986 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 }
2989 else if (curproxy == NULL) {
2990 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002994
2995 /* update the current file and line being parsed */
2996 curproxy->conf.args.file = curproxy->conf.file;
2997 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002998
2999 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02003000 if (!strcmp(args[0], "server") ||
3001 !strcmp(args[0], "default-server") ||
3002 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02003003 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3004 if (err_code & ERR_FATAL)
3005 goto out;
3006 }
3007 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003008 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003009 int cur_arg;
3010
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 if (curproxy == &defproxy) {
3012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003016 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018
Willy Tarreau24709282013-03-10 21:32:12 +01003019 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003020 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003025
Willy Tarreaua261e9b2016-12-22 20:44:00 +01003026 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003027
3028 /* use default settings for unix sockets */
3029 bind_conf->ux.uid = global.unix_bind.ux.uid;
3030 bind_conf->ux.gid = global.unix_bind.ux.gid;
3031 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003032
3033 /* NOTE: the following line might create several listeners if there
3034 * are comma-separated IPs or port ranges. So all further processing
3035 * will have to be applied to all listeners created after last_listen.
3036 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003037 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3038 if (errmsg && *errmsg) {
3039 indent_msg(&errmsg, 2);
3040 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003041 }
3042 else
3043 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3044 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
3047 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003048
Willy Tarreau4348fad2012-09-20 16:48:07 +02003049 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3050 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003051 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003052 }
3053
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003054 cur_arg = 2;
3055 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003056 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003057 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003058 char *err;
3059
Willy Tarreau26982662012-09-12 23:17:10 +02003060 kw = bind_find_kw(args[cur_arg]);
3061 if (kw) {
3062 char *err = NULL;
3063 int code;
3064
3065 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003066 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3067 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003068 cur_arg += 1 + kw->skip ;
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
3071 }
3072
Willy Tarreau4348fad2012-09-20 16:48:07 +02003073 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003074 err_code |= code;
3075
3076 if (code) {
3077 if (err && *err) {
3078 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003079 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003080 }
3081 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003082 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3083 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003084 if (code & ERR_FATAL) {
3085 free(err);
3086 cur_arg += 1 + kw->skip;
3087 goto out;
3088 }
3089 }
3090 free(err);
3091 cur_arg += 1 + kw->skip;
3092 continue;
3093 }
3094
Willy Tarreau8638f482012-09-18 18:01:17 +02003095 err = NULL;
3096 if (!bind_dumped) {
3097 bind_dump_kws(&err);
3098 indent_msg(&err, 4);
3099 bind_dumped = 1;
3100 }
3101
3102 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3103 file, linenum, args[0], args[1], args[cur_arg],
3104 err ? " Registered keywords :" : "", err ? err : "");
3105 free(err);
3106
Willy Tarreau93893792009-07-23 13:19:11 +02003107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003109 }
Willy Tarreau93893792009-07-23 13:19:11 +02003110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 }
3112 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003113 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3115 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003119 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003121
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 /* flush useless bits */
3123 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003126 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003127 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003129
William Lallemanddf1425a2015-04-28 20:17:49 +02003130 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3131 goto out;
3132
Willy Tarreau1c47f852006-07-09 08:22:27 +02003133 if (!*args[1]) {
3134 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3135 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003138 }
3139
Willy Tarreaua534fea2008-08-03 12:19:50 +02003140 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003141 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003142 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003143 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003144 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3145
Willy Tarreau93893792009-07-23 13:19:11 +02003146 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003147 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003149 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3150 goto out;
3151
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3153 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3154 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3155 else {
3156 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 }
3160 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003161 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003162 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003163
3164 if (curproxy == &defproxy) {
3165 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3166 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003169 }
3170
William Lallemanddf1425a2015-04-28 20:17:49 +02003171 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3172 goto out;
3173
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003174 if (!*args[1]) {
3175 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3176 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003179 }
3180
3181 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003182 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003183 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003184
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003185 if (curproxy->uuid <= 0) {
3186 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003187 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003190 }
3191
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003192 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3193 if (node) {
3194 struct proxy *target = container_of(node, struct proxy, conf.id);
3195 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3196 file, linenum, proxy_type_str(curproxy), curproxy->id,
3197 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
3200 }
3201 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003202 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003203 else if (!strcmp(args[0], "description")) {
3204 int i, len=0;
3205 char *d;
3206
Cyril Bonté99ed3272010-01-24 23:29:44 +01003207 if (curproxy == &defproxy) {
3208 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3209 file, linenum, args[0]);
3210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003214 if (!*args[1]) {
3215 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3216 file, linenum, args[0]);
3217 return -1;
3218 }
3219
Willy Tarreau348acfe2014-04-14 15:00:39 +02003220 for (i = 1; *args[i]; i++)
3221 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003222
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003223 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003224 curproxy->desc = d;
3225
Willy Tarreau348acfe2014-04-14 15:00:39 +02003226 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3227 for (i = 2; *args[i]; i++)
3228 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003229
3230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003232 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 curproxy->state = PR_STSTOPPED;
3235 }
3236 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003237 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 curproxy->state = PR_STNEW;
3240 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003241 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3242 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003243 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003244
3245 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003246 unsigned int low, high;
3247
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003248 if (strcmp(args[cur_arg], "all") == 0) {
3249 set = 0;
3250 break;
3251 }
3252 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003253 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003254 }
3255 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003256 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003257 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003258 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003259 char *dash = strchr(args[cur_arg], '-');
3260
3261 low = high = str2uic(args[cur_arg]);
3262 if (dash)
3263 high = str2uic(dash + 1);
3264
3265 if (high < low) {
3266 unsigned int swap = low;
3267 low = high;
3268 high = swap;
3269 }
3270
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003271 if (low < 1 || high > LONGBITS) {
3272 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3273 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003276 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003277 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003278 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003279 }
3280 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003281 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3282 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003285 }
3286 cur_arg++;
3287 }
3288 curproxy->bind_proc = set;
3289 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003290 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003291 if (curproxy == &defproxy) {
3292 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003295 }
3296
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003297 err = invalid_char(args[1]);
3298 if (err) {
3299 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3300 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003302 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003303 }
3304
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003305 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003306 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3307 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003310 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003311 }
3312 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3313
3314 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3315 err_code |= ERR_WARN;
3316
3317 if (*(args[1]) == 0) {
3318 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3319 file, linenum, args[0]);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322 }
3323 free(curproxy->dyncookie_key);
3324 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3327 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328
Willy Tarreau977b8e42006-12-29 14:19:17 +01003329 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003331
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 if (*(args[1]) == 0) {
3333 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3334 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003338
Willy Tarreau67402132012-05-31 20:40:20 +02003339 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003340 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003341 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003342 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 curproxy->cookie_name = strdup(args[1]);
3344 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003345
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 cur_arg = 2;
3347 while (*(args[cur_arg])) {
3348 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003349 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 }
3351 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003352 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
3354 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003355 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
3357 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003358 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
3360 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003361 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003363 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003364 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003367 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003369 else if (!strcmp(args[cur_arg], "httponly")) {
3370 curproxy->ck_opts |= PR_CK_HTTPONLY;
3371 }
3372 else if (!strcmp(args[cur_arg], "secure")) {
3373 curproxy->ck_opts |= PR_CK_SECURE;
3374 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003375 else if (!strcmp(args[cur_arg], "domain")) {
3376 if (!*args[cur_arg + 1]) {
3377 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3378 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003381 }
3382
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003383 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003384 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003385 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3386 " dots nor does not start with a dot."
3387 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003388 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003389 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003390 }
3391
3392 err = invalid_domainchar(args[cur_arg + 1]);
3393 if (err) {
3394 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3395 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003398 }
3399
Willy Tarreau68a897b2009-12-03 23:28:34 +01003400 if (!curproxy->cookie_domain) {
3401 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3402 } else {
3403 /* one domain was already specified, add another one by
3404 * building the string which will be returned along with
3405 * the cookie.
3406 */
3407 char *new_ptr;
3408 int new_len = strlen(curproxy->cookie_domain) +
3409 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3410 new_ptr = malloc(new_len);
3411 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3412 free(curproxy->cookie_domain);
3413 curproxy->cookie_domain = new_ptr;
3414 }
Willy Tarreau31936852010-10-06 16:59:56 +02003415 cur_arg++;
3416 }
3417 else if (!strcmp(args[cur_arg], "maxidle")) {
3418 unsigned int maxidle;
3419 const char *res;
3420
3421 if (!*args[cur_arg + 1]) {
3422 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3423 file, linenum, args[cur_arg]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427
3428 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3429 if (res) {
3430 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3431 file, linenum, *res, args[cur_arg]);
3432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
3434 }
3435 curproxy->cookie_maxidle = maxidle;
3436 cur_arg++;
3437 }
3438 else if (!strcmp(args[cur_arg], "maxlife")) {
3439 unsigned int maxlife;
3440 const char *res;
3441
3442 if (!*args[cur_arg + 1]) {
3443 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3444 file, linenum, args[cur_arg]);
3445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
3447 }
3448
3449 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3450 if (res) {
3451 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3452 file, linenum, *res, args[cur_arg]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003457 cur_arg++;
3458 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003459 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003460
3461 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3462 err_code |= ERR_WARN;
3463 curproxy->ck_opts |= PR_CK_DYNAMIC;
3464 }
3465
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003467 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 +02003468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471 }
3472 cur_arg++;
3473 }
Willy Tarreau67402132012-05-31 20:40:20 +02003474 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3476 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 }
3479
Willy Tarreau67402132012-05-31 20:40:20 +02003480 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3482 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003485
Willy Tarreau67402132012-05-31 20:40:20 +02003486 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003487 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3488 file, linenum);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003492 else if (!strcmp(args[0], "email-alert")) {
3493 if (*(args[1]) == 0) {
3494 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3495 file, linenum, args[0]);
3496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
3498 }
3499
3500 if (!strcmp(args[1], "from")) {
3501 if (*(args[1]) == 0) {
3502 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3503 file, linenum, args[1]);
3504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
3506 }
3507 free(curproxy->email_alert.from);
3508 curproxy->email_alert.from = strdup(args[2]);
3509 }
3510 else if (!strcmp(args[1], "mailers")) {
3511 if (*(args[1]) == 0) {
3512 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3513 file, linenum, args[1]);
3514 err_code |= ERR_ALERT | ERR_FATAL;
3515 goto out;
3516 }
3517 free(curproxy->email_alert.mailers.name);
3518 curproxy->email_alert.mailers.name = strdup(args[2]);
3519 }
3520 else if (!strcmp(args[1], "myhostname")) {
3521 if (*(args[1]) == 0) {
3522 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3523 file, linenum, args[1]);
3524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
3526 }
3527 free(curproxy->email_alert.myhostname);
3528 curproxy->email_alert.myhostname = strdup(args[2]);
3529 }
Simon Horman64e34162015-02-06 11:11:57 +09003530 else if (!strcmp(args[1], "level")) {
3531 curproxy->email_alert.level = get_log_level(args[2]);
3532 if (curproxy->email_alert.level < 0) {
3533 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3534 file, linenum, args[1], args[2]);
3535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
3537 }
3538 }
Simon Horman9dc49962015-01-30 11:22:59 +09003539 else if (!strcmp(args[1], "to")) {
3540 if (*(args[1]) == 0) {
3541 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3542 file, linenum, args[1]);
3543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
3545 }
3546 free(curproxy->email_alert.to);
3547 curproxy->email_alert.to = strdup(args[2]);
3548 }
3549 else {
3550 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3551 file, linenum, args[1]);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
3554 }
Simon Horman64e34162015-02-06 11:11:57 +09003555 /* Indicate that the email_alert is at least partially configured */
3556 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003557 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003558 else if (!strcmp(args[0], "external-check")) {
3559 if (*(args[1]) == 0) {
3560 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3561 file, linenum, args[0]);
3562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
3564 }
3565
3566 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003567 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003568 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003569 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003570 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3571 file, linenum, args[1]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
3575 free(curproxy->check_command);
3576 curproxy->check_command = strdup(args[2]);
3577 }
3578 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003579 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003580 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003581 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003582 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3583 file, linenum, args[1]);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586 }
3587 free(curproxy->check_path);
3588 curproxy->check_path = strdup(args[2]);
3589 }
3590 else {
3591 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3592 file, linenum, args[1]);
3593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
3595 }
3596 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003597 else if (!strcmp(args[0], "persist")) { /* persist */
3598 if (*(args[1]) == 0) {
3599 Alert("parsing [%s:%d] : missing persist method.\n",
3600 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003603 }
3604
3605 if (!strncmp(args[1], "rdp-cookie", 10)) {
3606 curproxy->options2 |= PR_O2_RDPC_PRST;
3607
Emeric Brunb982a3d2010-01-04 15:45:53 +01003608 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003609 const char *beg, *end;
3610
3611 beg = args[1] + 11;
3612 end = strchr(beg, ')');
3613
William Lallemanddf1425a2015-04-28 20:17:49 +02003614 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3615 goto out;
3616
Emeric Brun647caf12009-06-30 17:57:00 +02003617 if (!end || end == beg) {
3618 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3619 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003622 }
3623
3624 free(curproxy->rdp_cookie_name);
3625 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3626 curproxy->rdp_cookie_len = end-beg;
3627 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003628 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003629 free(curproxy->rdp_cookie_name);
3630 curproxy->rdp_cookie_name = strdup("msts");
3631 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3632 }
3633 else { /* syntax */
3634 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3635 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003638 }
3639 }
3640 else {
3641 Alert("parsing [%s:%d] : unknown persist method.\n",
3642 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003645 }
3646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003648 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
3651 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003652 else if (!strcmp(args[0], "load-server-state-from-file")) {
3653 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3654 err_code |= ERR_WARN;
3655 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3656 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3657 }
3658 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3659 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3660 }
3661 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3662 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3663 }
3664 else {
3665 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3666 file, linenum, args[0], args[1]);
3667 err_code |= ERR_ALERT | ERR_FATAL;
3668 goto out;
3669 }
3670 }
3671 else if (!strcmp(args[0], "server-state-file-name")) {
3672 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3673 err_code |= ERR_WARN;
3674 if (*(args[1]) == 0) {
3675 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3676 file, linenum, args[0]);
3677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
3679 }
3680 else if (!strcmp(args[1], "use-backend-name"))
3681 curproxy->server_state_file_name = strdup(curproxy->id);
3682 else
3683 curproxy->server_state_file_name = strdup(args[1]);
3684 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003686 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003688
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003690 if (curproxy == &defproxy) {
3691 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
3694 }
3695
William Lallemand1a748ae2015-05-19 16:37:23 +02003696 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3697 goto out;
3698
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 if (*(args[4]) == 0) {
3700 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3701 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003705 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 curproxy->capture_name = strdup(args[2]);
3707 curproxy->capture_namelen = strlen(curproxy->capture_name);
3708 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 curproxy->to_log |= LW_COOKIE;
3710 }
3711 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3712 struct cap_hdr *hdr;
3713
3714 if (curproxy == &defproxy) {
3715 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 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
3719
William Lallemand1a748ae2015-05-19 16:37:23 +02003720 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3721 goto out;
3722
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3724 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3725 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
3729
Vincent Bernat02779b62016-04-03 13:48:43 +02003730 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 hdr->next = curproxy->req_cap;
3732 hdr->name = strdup(args[3]);
3733 hdr->namelen = strlen(args[3]);
3734 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003735 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 hdr->index = curproxy->nb_req_cap++;
3737 curproxy->req_cap = hdr;
3738 curproxy->to_log |= LW_REQHDR;
3739 }
3740 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3741 struct cap_hdr *hdr;
3742
3743 if (curproxy == &defproxy) {
3744 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 }
3748
William Lallemand1a748ae2015-05-19 16:37:23 +02003749 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3750 goto out;
3751
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3753 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3754 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003758 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 hdr->next = curproxy->rsp_cap;
3760 hdr->name = strdup(args[3]);
3761 hdr->namelen = strlen(args[3]);
3762 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003763 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 hdr->index = curproxy->nb_rsp_cap++;
3765 curproxy->rsp_cap = hdr;
3766 curproxy->to_log |= LW_RSPHDR;
3767 }
3768 else {
3769 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3770 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 }
3774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003778
William Lallemanddf1425a2015-04-28 20:17:49 +02003779 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3780 goto out;
3781
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 if (*(args[1]) == 0) {
3783 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3784 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 }
3788 curproxy->conn_retries = atol(args[1]);
3789 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003790 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003791 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003792
3793 if (curproxy == &defproxy) {
3794 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
3797 }
3798
Willy Tarreau20b0de52012-12-24 15:45:22 +01003799 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003800 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003801 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3802 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3803 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3804 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003805 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 +01003806 file, linenum, args[0]);
3807 err_code |= ERR_WARN;
3808 }
3809
Willy Tarreauff011f22011-01-06 17:51:27 +01003810 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003811
Willy Tarreauff011f22011-01-06 17:51:27 +01003812 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003813 err_code |= ERR_ALERT | ERR_ABORT;
3814 goto out;
3815 }
3816
Willy Tarreau5002f572014-04-23 01:32:02 +02003817 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003818 err_code |= warnif_cond_conflicts(rule->cond,
3819 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3820 file, linenum);
3821
Willy Tarreauff011f22011-01-06 17:51:27 +01003822 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003823 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003824 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003825 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003826
3827 if (curproxy == &defproxy) {
3828 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832
3833 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003834 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003835 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3836 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003837 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3838 file, linenum, args[0]);
3839 err_code |= ERR_WARN;
3840 }
3841
3842 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3843
3844 if (!rule) {
3845 err_code |= ERR_ALERT | ERR_ABORT;
3846 goto out;
3847 }
3848
3849 err_code |= warnif_cond_conflicts(rule->cond,
3850 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3851 file, linenum);
3852
3853 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3854 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003855 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3856 /* set the header name and length into the proxy structure */
3857 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3858 err_code |= ERR_WARN;
3859
3860 if (!*args[1]) {
3861 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3862 file, linenum, args[0]);
3863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866
3867 /* set the desired header name */
3868 free(curproxy->server_id_hdr_name);
3869 curproxy->server_id_hdr_name = strdup(args[1]);
3870 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3871 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003872 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003873 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003874
Willy Tarreaub099aca2008-10-12 17:26:37 +02003875 if (curproxy == &defproxy) {
3876 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003879 }
3880
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003881 /* emulate "block" using "http-request block". Since these rules are supposed to
3882 * be processed before all http-request rules, we put them into their own list
3883 * and will insert them at the end.
3884 */
3885 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3886 if (!rule) {
3887 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003888 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003889 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003890 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3891 err_code |= warnif_cond_conflicts(rule->cond,
3892 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3893 file, linenum);
3894 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003895
3896 if (!already_warned(WARN_BLOCK_DEPRECATED))
3897 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]);
3898
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003899 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003900 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003901 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003902
Cyril Bonté99ed3272010-01-24 23:29:44 +01003903 if (curproxy == &defproxy) {
3904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
3907 }
3908
Willy Tarreaube4653b2015-05-28 15:26:58 +02003909 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003910 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3911 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003914 }
3915
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003916 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003917 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003918 err_code |= warnif_cond_conflicts(rule->cond,
3919 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3920 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003921 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003922 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003923 struct switching_rule *rule;
3924
Willy Tarreaub099aca2008-10-12 17:26:37 +02003925 if (curproxy == &defproxy) {
3926 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003929 }
3930
Willy Tarreau55ea7572007-06-17 19:56:27 +02003931 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003933
3934 if (*(args[1]) == 0) {
3935 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003938 }
3939
Willy Tarreauf51658d2014-04-23 01:21:56 +02003940 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003941 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003942 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3943 file, linenum, errmsg);
3944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
3946 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003947
Willy Tarreauf51658d2014-04-23 01:21:56 +02003948 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003949 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003950 else if (*args[2]) {
3951 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3952 file, linenum, args[2]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003956
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003957 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003958 if (!rule) {
3959 Alert("Out of memory error.\n");
3960 goto out;
3961 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003962 rule->cond = cond;
3963 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003964 rule->line = linenum;
3965 rule->file = strdup(file);
3966 if (!rule->file) {
3967 Alert("Out of memory error.\n");
3968 goto out;
3969 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003970 LIST_INIT(&rule->list);
3971 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3972 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003973 else if (strcmp(args[0], "use-server") == 0) {
3974 struct server_rule *rule;
3975
3976 if (curproxy == &defproxy) {
3977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
3980 }
3981
3982 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3983 err_code |= ERR_WARN;
3984
3985 if (*(args[1]) == 0) {
3986 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
3990
3991 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3992 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3993 file, linenum, args[0]);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
3996 }
3997
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003998 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003999 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4000 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
4003 }
4004
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004005 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004006
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004007 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004008 rule->cond = cond;
4009 rule->srv.name = strdup(args[1]);
4010 LIST_INIT(&rule->list);
4011 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4012 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4013 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004014 else if ((!strcmp(args[0], "force-persist")) ||
4015 (!strcmp(args[0], "ignore-persist"))) {
4016 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004017
4018 if (curproxy == &defproxy) {
4019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
4022 }
4023
4024 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4025 err_code |= ERR_WARN;
4026
Willy Tarreauef6494c2010-01-28 17:12:36 +01004027 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004028 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4029 file, linenum, args[0]);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
4033
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004034 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004035 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4036 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
4039 }
4040
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004041 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4042 * where force-persist is applied.
4043 */
4044 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004045
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004046 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004047 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004048 if (!strcmp(args[0], "force-persist")) {
4049 rule->type = PERSIST_TYPE_FORCE;
4050 } else {
4051 rule->type = PERSIST_TYPE_IGNORE;
4052 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004053 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004054 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004055 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004056 else if (!strcmp(args[0], "stick-table")) {
4057 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004058 struct proxy *other;
4059
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004060 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004061 if (other) {
4062 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4063 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
4066 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004067
Emeric Brun32da3c42010-09-23 18:39:19 +02004068 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004069 curproxy->table.type = (unsigned int)-1;
4070 while (*args[myidx]) {
4071 const char *err;
4072
4073 if (strcmp(args[myidx], "size") == 0) {
4074 myidx++;
4075 if (!*(args[myidx])) {
4076 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4077 file, linenum, args[myidx-1]);
4078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
4080 }
4081 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4082 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4083 file, linenum, *err, args[myidx-1]);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004087 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004089 else if (strcmp(args[myidx], "peers") == 0) {
4090 myidx++;
Godbach50523162013-12-11 19:48:57 +08004091 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004092 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4093 file, linenum, args[myidx-1]);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
Godbach50523162013-12-11 19:48:57 +08004096 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004097 curproxy->table.peers.name = strdup(args[myidx++]);
4098 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099 else if (strcmp(args[myidx], "expire") == 0) {
4100 myidx++;
4101 if (!*(args[myidx])) {
4102 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4103 file, linenum, args[myidx-1]);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
4107 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4108 if (err) {
4109 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4110 file, linenum, *err, args[myidx-1]);
4111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
4113 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004114 if (val > INT_MAX) {
4115 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4116 file, linenum, val);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004120 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004121 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004122 }
4123 else if (strcmp(args[myidx], "nopurge") == 0) {
4124 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004125 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004126 }
4127 else if (strcmp(args[myidx], "type") == 0) {
4128 myidx++;
4129 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4130 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4131 file, linenum, args[myidx]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004135 /* myidx already points to next arg */
4136 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004137 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004138 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004139 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004140
4141 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004142 nw = args[myidx];
4143 while (*nw) {
4144 /* the "store" keyword supports a comma-separated list */
4145 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004146 sa = NULL; /* store arg */
4147 while (*nw && *nw != ',') {
4148 if (*nw == '(') {
4149 *nw = 0;
4150 sa = ++nw;
4151 while (*nw != ')') {
4152 if (!*nw) {
4153 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4154 file, linenum, args[0], cw);
4155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
4157 }
4158 nw++;
4159 }
4160 *nw = '\0';
4161 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004162 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004163 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004164 if (*nw)
4165 *nw++ = '\0';
4166 type = stktable_get_data_type(cw);
4167 if (type < 0) {
4168 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4169 file, linenum, args[0], cw);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
Willy Tarreauac782882010-06-20 10:41:54 +02004173
4174 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4175 switch (err) {
4176 case PE_NONE: break;
4177 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004178 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4179 file, linenum, args[0], cw);
4180 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004181 break;
4182
4183 case PE_ARG_MISSING:
4184 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4185 file, linenum, args[0], cw);
4186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
4188
4189 case PE_ARG_NOT_USED:
4190 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4191 file, linenum, args[0], cw);
4192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
4194
4195 default:
4196 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4197 file, linenum, args[0], cw);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004200 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004201 }
4202 myidx++;
4203 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004204 else {
4205 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4206 file, linenum, args[myidx]);
4207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004209 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004210 }
4211
4212 if (!curproxy->table.size) {
4213 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4214 file, linenum);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217 }
4218
4219 if (curproxy->table.type == (unsigned int)-1) {
4220 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4221 file, linenum);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 }
4225 }
4226 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004227 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004228 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004229 int myidx = 0;
4230 const char *name = NULL;
4231 int flags;
4232
4233 if (curproxy == &defproxy) {
4234 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 }
4238
4239 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4240 err_code |= ERR_WARN;
4241 goto out;
4242 }
4243
4244 myidx++;
4245 if ((strcmp(args[myidx], "store") == 0) ||
4246 (strcmp(args[myidx], "store-request") == 0)) {
4247 myidx++;
4248 flags = STK_IS_STORE;
4249 }
4250 else if (strcmp(args[myidx], "store-response") == 0) {
4251 myidx++;
4252 flags = STK_IS_STORE | STK_ON_RSP;
4253 }
4254 else if (strcmp(args[myidx], "match") == 0) {
4255 myidx++;
4256 flags = STK_IS_MATCH;
4257 }
4258 else if (strcmp(args[myidx], "on") == 0) {
4259 myidx++;
4260 flags = STK_IS_MATCH | STK_IS_STORE;
4261 }
4262 else {
4263 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
4266 }
4267
4268 if (*(args[myidx]) == 0) {
4269 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
4272 }
4273
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004274 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004275 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004276 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004277 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
4280 }
4281
4282 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004283 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4284 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4285 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004286 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004287 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004288 goto out;
4289 }
4290 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004291 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4292 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4293 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004294 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004295 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004296 goto out;
4297 }
4298 }
4299
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004300 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004301 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004302
Emeric Brunb982a3d2010-01-04 15:45:53 +01004303 if (strcmp(args[myidx], "table") == 0) {
4304 myidx++;
4305 name = args[myidx++];
4306 }
4307
Willy Tarreauef6494c2010-01-28 17:12:36 +01004308 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004309 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004310 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4311 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004312 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004313 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004314 goto out;
4315 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004316 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004317 else if (*(args[myidx])) {
4318 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4319 file, linenum, args[0], args[myidx]);
4320 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004321 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004322 goto out;
4323 }
Emeric Brun97679e72010-09-23 17:56:44 +02004324 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004325 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004326 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004327 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004328
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004329 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004330 rule->cond = cond;
4331 rule->expr = expr;
4332 rule->flags = flags;
4333 rule->table.name = name ? strdup(name) : NULL;
4334 LIST_INIT(&rule->list);
4335 if (flags & STK_ON_RSP)
4336 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4337 else
4338 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 else if (!strcmp(args[0], "stats")) {
4341 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4342 curproxy->uri_auth = NULL; /* we must detach from the default config */
4343
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004344 if (!*args[1]) {
4345 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004346 } else if (!strcmp(args[1], "admin")) {
4347 struct stats_admin_rule *rule;
4348
4349 if (curproxy == &defproxy) {
4350 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354
4355 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4356 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4357 err_code |= ERR_ALERT | ERR_ABORT;
4358 goto out;
4359 }
4360
4361 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4362 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4363 file, linenum, args[0], args[1]);
4364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
4366 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004367 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004368 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4369 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004374 err_code |= warnif_cond_conflicts(cond,
4375 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4376 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004377
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004378 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004379 rule->cond = cond;
4380 LIST_INIT(&rule->list);
4381 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004382 } else if (!strcmp(args[1], "uri")) {
4383 if (*(args[2]) == 0) {
4384 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4388 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004389 err_code |= ERR_ALERT | ERR_ABORT;
4390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 }
4392 } else if (!strcmp(args[1], "realm")) {
4393 if (*(args[2]) == 0) {
4394 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4398 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004399 err_code |= ERR_ALERT | ERR_ABORT;
4400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004402 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004403 unsigned interval;
4404
4405 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4406 if (err) {
4407 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4408 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004411 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4412 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_ABORT;
4414 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004415 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004416 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004417 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004418
4419 if (curproxy == &defproxy) {
4420 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
4423 }
4424
4425 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4426 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4427 err_code |= ERR_ALERT | ERR_ABORT;
4428 goto out;
4429 }
4430
Willy Tarreauff011f22011-01-06 17:51:27 +01004431 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004432 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004433 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4434 file, linenum, args[0]);
4435 err_code |= ERR_WARN;
4436 }
4437
Willy Tarreauff011f22011-01-06 17:51:27 +01004438 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004439
Willy Tarreauff011f22011-01-06 17:51:27 +01004440 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004441 err_code |= ERR_ALERT | ERR_ABORT;
4442 goto out;
4443 }
4444
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004445 err_code |= warnif_cond_conflicts(rule->cond,
4446 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4447 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004448 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004449
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 } else if (!strcmp(args[1], "auth")) {
4451 if (*(args[2]) == 0) {
4452 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004455 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4456 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004457 err_code |= ERR_ALERT | ERR_ABORT;
4458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 }
4460 } else if (!strcmp(args[1], "scope")) {
4461 if (*(args[2]) == 0) {
4462 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4466 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004467 err_code |= ERR_ALERT | ERR_ABORT;
4468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004469 }
4470 } else if (!strcmp(args[1], "enable")) {
4471 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4472 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_ABORT;
4474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004476 } else if (!strcmp(args[1], "hide-version")) {
4477 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4478 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004479 err_code |= ERR_ALERT | ERR_ABORT;
4480 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004481 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004482 } else if (!strcmp(args[1], "show-legends")) {
4483 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4485 err_code |= ERR_ALERT | ERR_ABORT;
4486 goto out;
4487 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004488 } else if (!strcmp(args[1], "show-node")) {
4489
4490 if (*args[2]) {
4491 int i;
4492 char c;
4493
4494 for (i=0; args[2][i]; i++) {
4495 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004496 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4497 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004498 break;
4499 }
4500
4501 if (!i || args[2][i]) {
4502 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4503 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4504 file, linenum, args[0], args[1]);
4505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
4508 }
4509
4510 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4511 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4512 err_code |= ERR_ALERT | ERR_ABORT;
4513 goto out;
4514 }
4515 } else if (!strcmp(args[1], "show-desc")) {
4516 char *desc = NULL;
4517
4518 if (*args[2]) {
4519 int i, len=0;
4520 char *d;
4521
Willy Tarreau348acfe2014-04-14 15:00:39 +02004522 for (i = 2; *args[i]; i++)
4523 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004524
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004525 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004526
Willy Tarreau348acfe2014-04-14 15:00:39 +02004527 d += snprintf(d, desc + len - d, "%s", args[2]);
4528 for (i = 3; *args[i]; i++)
4529 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004530 }
4531
4532 if (!*args[2] && !global.desc)
4533 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4534 file, linenum, args[1]);
4535 else {
4536 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4537 free(desc);
4538 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4539 err_code |= ERR_ALERT | ERR_ABORT;
4540 goto out;
4541 }
4542 free(desc);
4543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004545stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004546 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 +01004547 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004550 }
4551 }
4552 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004553 int optnum;
4554
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004555 if (*(args[1]) == '\0') {
4556 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004560 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004561
4562 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4563 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004564 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4565 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4566 file, linenum, cfg_opts[optnum].name);
4567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
4569 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004570 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4571 goto out;
4572
Willy Tarreau93893792009-07-23 13:19:11 +02004573 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4574 err_code |= ERR_WARN;
4575 goto out;
4576 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004577
Willy Tarreau3842f002009-06-14 11:39:52 +02004578 curproxy->no_options &= ~cfg_opts[optnum].val;
4579 curproxy->options &= ~cfg_opts[optnum].val;
4580
4581 switch (kwm) {
4582 case KWM_STD:
4583 curproxy->options |= cfg_opts[optnum].val;
4584 break;
4585 case KWM_NO:
4586 curproxy->no_options |= cfg_opts[optnum].val;
4587 break;
4588 case KWM_DEF: /* already cleared */
4589 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004590 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004591
Willy Tarreau93893792009-07-23 13:19:11 +02004592 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004593 }
4594 }
4595
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004596 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4597 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004598 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4599 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4600 file, linenum, cfg_opts2[optnum].name);
4601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
4603 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004604 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4605 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004606 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4607 err_code |= ERR_WARN;
4608 goto out;
4609 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004610
Willy Tarreau3842f002009-06-14 11:39:52 +02004611 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4612 curproxy->options2 &= ~cfg_opts2[optnum].val;
4613
4614 switch (kwm) {
4615 case KWM_STD:
4616 curproxy->options2 |= cfg_opts2[optnum].val;
4617 break;
4618 case KWM_NO:
4619 curproxy->no_options2 |= cfg_opts2[optnum].val;
4620 break;
4621 case KWM_DEF: /* already cleared */
4622 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004623 }
Willy Tarreau93893792009-07-23 13:19:11 +02004624 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004625 }
4626 }
4627
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004628 /* HTTP options override each other. They can be cancelled using
4629 * "no option xxx" which only switches to default mode if the mode
4630 * was this one (useful for cancelling options set in defaults
4631 * sections).
4632 */
4633 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004634 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4635 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004636 if (kwm == KWM_STD) {
4637 curproxy->options &= ~PR_O_HTTP_MODE;
4638 curproxy->options |= PR_O_HTTP_PCL;
4639 goto out;
4640 }
4641 else if (kwm == KWM_NO) {
4642 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4643 curproxy->options &= ~PR_O_HTTP_MODE;
4644 goto out;
4645 }
4646 }
4647 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004648 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4649 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004650 if (kwm == KWM_STD) {
4651 curproxy->options &= ~PR_O_HTTP_MODE;
4652 curproxy->options |= PR_O_HTTP_FCL;
4653 goto out;
4654 }
4655 else if (kwm == KWM_NO) {
4656 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4657 curproxy->options &= ~PR_O_HTTP_MODE;
4658 goto out;
4659 }
4660 }
4661 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004662 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4663 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004664 if (kwm == KWM_STD) {
4665 curproxy->options &= ~PR_O_HTTP_MODE;
4666 curproxy->options |= PR_O_HTTP_SCL;
4667 goto out;
4668 }
4669 else if (kwm == KWM_NO) {
4670 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4671 curproxy->options &= ~PR_O_HTTP_MODE;
4672 goto out;
4673 }
4674 }
4675 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004676 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4677 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004678 if (kwm == KWM_STD) {
4679 curproxy->options &= ~PR_O_HTTP_MODE;
4680 curproxy->options |= PR_O_HTTP_KAL;
4681 goto out;
4682 }
4683 else if (kwm == KWM_NO) {
4684 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4685 curproxy->options &= ~PR_O_HTTP_MODE;
4686 goto out;
4687 }
4688 }
4689 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004690 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4691 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004692 if (kwm == KWM_STD) {
4693 curproxy->options &= ~PR_O_HTTP_MODE;
4694 curproxy->options |= PR_O_HTTP_TUN;
4695 goto out;
4696 }
4697 else if (kwm == KWM_NO) {
4698 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4699 curproxy->options &= ~PR_O_HTTP_MODE;
4700 goto out;
4701 }
4702 }
4703
Joseph Lynch726ab712015-05-11 23:25:34 -07004704 /* Redispatch can take an integer argument that control when the
4705 * resispatch occurs. All values are relative to the retries option.
4706 * This can be cancelled using "no option xxx".
4707 */
4708 if (strcmp(args[1], "redispatch") == 0) {
4709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4710 err_code |= ERR_WARN;
4711 goto out;
4712 }
4713
4714 curproxy->no_options &= ~PR_O_REDISP;
4715 curproxy->options &= ~PR_O_REDISP;
4716
4717 switch (kwm) {
4718 case KWM_STD:
4719 curproxy->options |= PR_O_REDISP;
4720 curproxy->redispatch_after = -1;
4721 if(*args[2]) {
4722 curproxy->redispatch_after = atol(args[2]);
4723 }
4724 break;
4725 case KWM_NO:
4726 curproxy->no_options |= PR_O_REDISP;
4727 curproxy->redispatch_after = 0;
4728 break;
4729 case KWM_DEF: /* already cleared */
4730 break;
4731 }
4732 goto out;
4733 }
4734
Willy Tarreau3842f002009-06-14 11:39:52 +02004735 if (kwm != KWM_STD) {
4736 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004737 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004740 }
4741
Emeric Brun3a058f32009-06-30 18:26:00 +02004742 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004743 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004745 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004746 if (*(args[2]) != '\0') {
4747 if (!strcmp(args[2], "clf")) {
4748 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004749 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004750 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004751 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004752 err_code |= ERR_ALERT | ERR_FATAL;
4753 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004754 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004755 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4756 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004757 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004758 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4759 char *oldlogformat = "log-format";
4760 char *clflogformat = "";
4761
4762 if (curproxy->conf.logformat_string == default_http_log_format)
4763 oldlogformat = "option httplog";
4764 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4765 oldlogformat = "option tcplog";
4766 else if (curproxy->conf.logformat_string == clf_http_log_format)
4767 oldlogformat = "option httplog clf";
4768 if (logformat == clf_http_log_format)
4769 clflogformat = " clf";
4770 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4771 file, linenum, clflogformat, oldlogformat);
4772 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004773 if (curproxy->conf.logformat_string != default_http_log_format &&
4774 curproxy->conf.logformat_string != default_tcp_log_format &&
4775 curproxy->conf.logformat_string != clf_http_log_format)
4776 free(curproxy->conf.logformat_string);
4777 curproxy->conf.logformat_string = logformat;
4778
4779 free(curproxy->conf.lfs_file);
4780 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4781 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004782 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004783 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004784 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4785 char *oldlogformat = "log-format";
4786
4787 if (curproxy->conf.logformat_string == default_http_log_format)
4788 oldlogformat = "option httplog";
4789 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4790 oldlogformat = "option tcplog";
4791 else if (curproxy->conf.logformat_string == clf_http_log_format)
4792 oldlogformat = "option httplog clf";
4793 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4794 file, linenum, oldlogformat);
4795 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004797 if (curproxy->conf.logformat_string != default_http_log_format &&
4798 curproxy->conf.logformat_string != default_tcp_log_format &&
4799 curproxy->conf.logformat_string != clf_http_log_format)
4800 free(curproxy->conf.logformat_string);
4801 curproxy->conf.logformat_string = default_tcp_log_format;
4802
4803 free(curproxy->conf.lfs_file);
4804 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4805 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004806
4807 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4808 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004811 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004812 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004813 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004814
William Lallemanddf1425a2015-04-28 20:17:49 +02004815 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4816 goto out;
4817
Willy Tarreau13943ab2006-12-31 00:24:10 +01004818 if (curproxy->cap & PR_CAP_FE)
4819 curproxy->options |= PR_O_TCP_CLI_KA;
4820 if (curproxy->cap & PR_CAP_BE)
4821 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 }
4823 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004825 err_code |= ERR_WARN;
4826
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004828 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004829 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004830 curproxy->options2 &= ~PR_O2_CHK_ANY;
4831 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 if (!*args[2]) { /* no argument */
4833 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4834 curproxy->check_len = strlen(DEF_CHECK_REQ);
4835 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004836 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004837 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004839 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004841 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 if (*args[4])
4843 reqlen += strlen(args[4]);
4844 else
4845 reqlen += strlen("HTTP/1.0");
4846
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004847 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004849 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004851 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4852 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004853 }
4854 else if (!strcmp(args[1], "ssl-hello-chk")) {
4855 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004856 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004857 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004858
Willy Tarreaua534fea2008-08-03 12:19:50 +02004859 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004860 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004861 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004862 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004863
4864 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 }
Willy Tarreau23677902007-05-08 23:50:35 +02004867 else if (!strcmp(args[1], "smtpchk")) {
4868 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004869 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004870 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004871 curproxy->options2 &= ~PR_O2_CHK_ANY;
4872 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004873
4874 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4875 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4876 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4877 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4878 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4879 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004880 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004881 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4882 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4883 } else {
4884 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4885 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4886 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4887 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4888 }
4889 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004890 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4891 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004892 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004893 else if (!strcmp(args[1], "pgsql-check")) {
4894 /* use PostgreSQL request to check servers' health */
4895 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4896 err_code |= ERR_WARN;
4897
4898 free(curproxy->check_req);
4899 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004900 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004901 curproxy->options2 |= PR_O2_PGSQL_CHK;
4902
4903 if (*(args[2])) {
4904 int cur_arg = 2;
4905
4906 while (*(args[cur_arg])) {
4907 if (strcmp(args[cur_arg], "user") == 0) {
4908 char * packet;
4909 uint32_t packet_len;
4910 uint32_t pv;
4911
4912 /* suboption header - needs additional argument for it */
4913 if (*(args[cur_arg+1]) == 0) {
4914 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4915 file, linenum, args[0], args[1], args[cur_arg]);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
4919
4920 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4921 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4922 pv = htonl(0x30000); /* protocol version 3.0 */
4923
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004924 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004925
4926 memcpy(packet + 4, &pv, 4);
4927
4928 /* copy "user" */
4929 memcpy(packet + 8, "user", 4);
4930
4931 /* copy username */
4932 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4933
4934 free(curproxy->check_req);
4935 curproxy->check_req = packet;
4936 curproxy->check_len = packet_len;
4937
4938 packet_len = htonl(packet_len);
4939 memcpy(packet, &packet_len, 4);
4940 cur_arg += 2;
4941 } else {
4942 /* unknown suboption - catchall */
4943 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4944 file, linenum, args[0], args[1]);
4945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
4947 }
4948 } /* end while loop */
4949 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004950 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4951 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004952 }
4953
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004954 else if (!strcmp(args[1], "redis-check")) {
4955 /* use REDIS PING request to check servers' health */
4956 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4957 err_code |= ERR_WARN;
4958
4959 free(curproxy->check_req);
4960 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004961 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004962 curproxy->options2 |= PR_O2_REDIS_CHK;
4963
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004964 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004965 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4966 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004967
4968 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4969 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004970 }
4971
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004972 else if (!strcmp(args[1], "mysql-check")) {
4973 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004974 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4975 err_code |= ERR_WARN;
4976
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004977 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004978 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004979 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004980 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004981
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004982 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004983 * const char mysql40_client_auth_pkt[] = {
4984 * "\x0e\x00\x00" // packet length
4985 * "\x01" // packet number
4986 * "\x00\x00" // client capabilities
4987 * "\x00\x00\x01" // max packet
4988 * "haproxy\x00" // username (null terminated string)
4989 * "\x00" // filler (always 0x00)
4990 * "\x01\x00\x00" // packet length
4991 * "\x00" // packet number
4992 * "\x01" // COM_QUIT command
4993 * };
4994 */
4995
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004996 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4997 * const char mysql41_client_auth_pkt[] = {
4998 * "\x0e\x00\x00\" // packet length
4999 * "\x01" // packet number
5000 * "\x00\x00\x00\x00" // client capabilities
5001 * "\x00\x00\x00\x01" // max packet
5002 * "\x21" // character set (UTF-8)
5003 * char[23] // All zeroes
5004 * "haproxy\x00" // username (null terminated string)
5005 * "\x00" // filler (always 0x00)
5006 * "\x01\x00\x00" // packet length
5007 * "\x00" // packet number
5008 * "\x01" // COM_QUIT command
5009 * };
5010 */
5011
5012
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005013 if (*(args[2])) {
5014 int cur_arg = 2;
5015
5016 while (*(args[cur_arg])) {
5017 if (strcmp(args[cur_arg], "user") == 0) {
5018 char *mysqluser;
5019 int packetlen, reqlen, userlen;
5020
5021 /* suboption header - needs additional argument for it */
5022 if (*(args[cur_arg+1]) == 0) {
5023 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5024 file, linenum, args[0], args[1], args[cur_arg]);
5025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
5027 }
5028 mysqluser = args[cur_arg + 1];
5029 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005030
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005031 if (*(args[cur_arg+2])) {
5032 if (!strcmp(args[cur_arg+2], "post-41")) {
5033 packetlen = userlen + 7 + 27;
5034 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005035
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005036 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005037 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005038 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005039
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005040 snprintf(curproxy->check_req, 4, "%c%c%c",
5041 ((unsigned char) packetlen & 0xff),
5042 ((unsigned char) (packetlen >> 8) & 0xff),
5043 ((unsigned char) (packetlen >> 16) & 0xff));
5044
5045 curproxy->check_req[3] = 1;
5046 curproxy->check_req[5] = 130;
5047 curproxy->check_req[11] = 1;
5048 curproxy->check_req[12] = 33;
5049 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5050 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5051 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5052 cur_arg += 3;
5053 } else {
5054 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
5057 }
5058 } else {
5059 packetlen = userlen + 7;
5060 reqlen = packetlen + 9;
5061
5062 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005063 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005064 curproxy->check_len = reqlen;
5065
5066 snprintf(curproxy->check_req, 4, "%c%c%c",
5067 ((unsigned char) packetlen & 0xff),
5068 ((unsigned char) (packetlen >> 8) & 0xff),
5069 ((unsigned char) (packetlen >> 16) & 0xff));
5070
5071 curproxy->check_req[3] = 1;
5072 curproxy->check_req[5] = 128;
5073 curproxy->check_req[8] = 1;
5074 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5075 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5076 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5077 cur_arg += 2;
5078 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005079 } else {
5080 /* unknown suboption - catchall */
5081 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5082 file, linenum, args[0], args[1]);
5083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
5085 }
5086 } /* end while loop */
5087 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005088 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005089 else if (!strcmp(args[1], "ldap-check")) {
5090 /* use LDAP request to check servers' health */
5091 free(curproxy->check_req);
5092 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005093 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005094 curproxy->options2 |= PR_O2_LDAP_CHK;
5095
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005096 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005097 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5098 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005099 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5100 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005101 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005102 else if (!strcmp(args[1], "spop-check")) {
5103 if (curproxy == &defproxy) {
5104 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5105 file, linenum, args[0], args[1]);
5106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
5108 }
5109 if (curproxy->cap & PR_CAP_FE) {
5110 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5111 file, linenum, args[0], args[1]);
5112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
5114 }
5115
5116 /* use SPOE request to check servers' health */
5117 free(curproxy->check_req);
5118 curproxy->check_req = NULL;
5119 curproxy->options2 &= ~PR_O2_CHK_ANY;
5120 curproxy->options2 |= PR_O2_SPOP_CHK;
5121
Christopher Faulet8ef75252017-02-20 22:56:03 +01005122 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005123 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
5126 }
5127 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5128 goto out;
5129 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005130 else if (!strcmp(args[1], "tcp-check")) {
5131 /* use raw TCPCHK send/expect to check servers' health */
5132 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5133 err_code |= ERR_WARN;
5134
5135 free(curproxy->check_req);
5136 curproxy->check_req = NULL;
5137 curproxy->options2 &= ~PR_O2_CHK_ANY;
5138 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005139 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5140 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005141 }
Simon Horman98637e52014-06-20 12:30:16 +09005142 else if (!strcmp(args[1], "external-check")) {
5143 /* excute an external command to check servers' health */
5144 free(curproxy->check_req);
5145 curproxy->check_req = NULL;
5146 curproxy->options2 &= ~PR_O2_CHK_ANY;
5147 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005148 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5149 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005150 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005151 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005152 int cur_arg;
5153
5154 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5155 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005156 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005157
Willy Tarreau87cf5142011-08-19 22:57:24 +02005158 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005159
5160 free(curproxy->fwdfor_hdr_name);
5161 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5162 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5163
5164 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5165 cur_arg = 2;
5166 while (*(args[cur_arg])) {
5167 if (!strcmp(args[cur_arg], "except")) {
5168 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005169 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005170 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5171 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005174 }
5175 /* flush useless bits */
5176 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005177 cur_arg += 2;
5178 } else if (!strcmp(args[cur_arg], "header")) {
5179 /* suboption header - needs additional argument for it */
5180 if (*(args[cur_arg+1]) == 0) {
5181 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5182 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005185 }
5186 free(curproxy->fwdfor_hdr_name);
5187 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5188 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5189 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005190 } else if (!strcmp(args[cur_arg], "if-none")) {
5191 curproxy->options &= ~PR_O_FF_ALWAYS;
5192 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005193 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005194 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005195 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005196 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005199 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005200 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005201 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005202 else if (!strcmp(args[1], "originalto")) {
5203 int cur_arg;
5204
5205 /* insert x-original-to field, but not for the IP address listed as an except.
5206 * set default options (ie: bitfield, header name, etc)
5207 */
5208
5209 curproxy->options |= PR_O_ORGTO;
5210
5211 free(curproxy->orgto_hdr_name);
5212 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5213 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5214
Willy Tarreau87cf5142011-08-19 22:57:24 +02005215 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005216 cur_arg = 2;
5217 while (*(args[cur_arg])) {
5218 if (!strcmp(args[cur_arg], "except")) {
5219 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005220 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 +02005221 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5222 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005225 }
5226 /* flush useless bits */
5227 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5228 cur_arg += 2;
5229 } else if (!strcmp(args[cur_arg], "header")) {
5230 /* suboption header - needs additional argument for it */
5231 if (*(args[cur_arg+1]) == 0) {
5232 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5233 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005236 }
5237 free(curproxy->orgto_hdr_name);
5238 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5239 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5240 cur_arg += 2;
5241 } else {
5242 /* unknown suboption - catchall */
5243 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5244 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005247 }
5248 } /* end while loop */
5249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 else {
5251 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005252 err_code |= ERR_ALERT | ERR_FATAL;
5253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
Willy Tarreau93893792009-07-23 13:19:11 +02005255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005257 else if (!strcmp(args[0], "default_backend")) {
5258 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005259 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005260
5261 if (*(args[1]) == 0) {
5262 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005265 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005266 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005267 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005268
5269 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5270 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005274 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005275
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005276 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5277 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 +01005278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 /* enable reconnections to dispatch */
5281 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005282
5283 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005286 else if (!strcmp(args[0], "http-reuse")) {
5287 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5288 err_code |= ERR_WARN;
5289
5290 if (strcmp(args[1], "never") == 0) {
5291 /* enable a graceful server shutdown on an HTTP 404 response */
5292 curproxy->options &= ~PR_O_REUSE_MASK;
5293 curproxy->options |= PR_O_REUSE_NEVR;
5294 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5295 goto out;
5296 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005297 else if (strcmp(args[1], "safe") == 0) {
5298 /* enable a graceful server shutdown on an HTTP 404 response */
5299 curproxy->options &= ~PR_O_REUSE_MASK;
5300 curproxy->options |= PR_O_REUSE_SAFE;
5301 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5302 goto out;
5303 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005304 else if (strcmp(args[1], "aggressive") == 0) {
5305 curproxy->options &= ~PR_O_REUSE_MASK;
5306 curproxy->options |= PR_O_REUSE_AGGR;
5307 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5308 goto out;
5309 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005310 else if (strcmp(args[1], "always") == 0) {
5311 /* enable a graceful server shutdown on an HTTP 404 response */
5312 curproxy->options &= ~PR_O_REUSE_MASK;
5313 curproxy->options |= PR_O_REUSE_ALWS;
5314 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5315 goto out;
5316 }
5317 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005318 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
5321 }
5322 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005323 else if (!strcmp(args[0], "http-check")) {
5324 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005325 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005326
5327 if (strcmp(args[1], "disable-on-404") == 0) {
5328 /* enable a graceful server shutdown on an HTTP 404 response */
5329 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005330 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5331 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005332 }
Willy Tarreauef781042010-01-27 11:53:01 +01005333 else if (strcmp(args[1], "send-state") == 0) {
5334 /* enable emission of the apparent state of a server in HTTP checks */
5335 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005336 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5337 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005338 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005339 else if (strcmp(args[1], "expect") == 0) {
5340 const char *ptr_arg;
5341 int cur_arg;
5342
5343 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5344 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
5347 }
5348
5349 cur_arg = 2;
5350 /* consider exclamation marks, sole or at the beginning of a word */
5351 while (*(ptr_arg = args[cur_arg])) {
5352 while (*ptr_arg == '!') {
5353 curproxy->options2 ^= PR_O2_EXP_INV;
5354 ptr_arg++;
5355 }
5356 if (*ptr_arg)
5357 break;
5358 cur_arg++;
5359 }
5360 /* now ptr_arg points to the beginning of a word past any possible
5361 * exclamation mark, and cur_arg is the argument which holds this word.
5362 */
5363 if (strcmp(ptr_arg, "status") == 0) {
5364 if (!*(args[cur_arg + 1])) {
5365 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5366 file, linenum, args[0], args[1], ptr_arg);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005371 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005372 curproxy->expect_str = strdup(args[cur_arg + 1]);
5373 }
5374 else if (strcmp(ptr_arg, "string") == 0) {
5375 if (!*(args[cur_arg + 1])) {
5376 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5377 file, linenum, args[0], args[1], ptr_arg);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005382 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005383 curproxy->expect_str = strdup(args[cur_arg + 1]);
5384 }
5385 else if (strcmp(ptr_arg, "rstatus") == 0) {
5386 if (!*(args[cur_arg + 1])) {
5387 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5388 file, linenum, args[0], args[1], ptr_arg);
5389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
5391 }
5392 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005393 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005394 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005395 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005396 free(curproxy->expect_regex);
5397 curproxy->expect_regex = NULL;
5398 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005399 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005400 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5401 error = NULL;
5402 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5403 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5404 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5405 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
5409 }
5410 else if (strcmp(ptr_arg, "rstring") == 0) {
5411 if (!*(args[cur_arg + 1])) {
5412 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5413 file, linenum, args[0], args[1], ptr_arg);
5414 err_code |= ERR_ALERT | ERR_FATAL;
5415 goto out;
5416 }
5417 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005418 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005419 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005420 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005421 free(curproxy->expect_regex);
5422 curproxy->expect_regex = NULL;
5423 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005424 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005425 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5426 error = NULL;
5427 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5428 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5429 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5430 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
5434 }
5435 else {
5436 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5437 file, linenum, args[0], args[1], ptr_arg);
5438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
5441 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005442 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005443 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 +02005444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005446 }
5447 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005448 else if (!strcmp(args[0], "tcp-check")) {
5449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5450 err_code |= ERR_WARN;
5451
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005452 if (strcmp(args[1], "comment") == 0) {
5453 int cur_arg;
5454 struct tcpcheck_rule *tcpcheck;
5455
5456 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005457 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005458 tcpcheck->action = TCPCHK_ACT_COMMENT;
5459
5460 if (!*args[cur_arg + 1]) {
5461 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5462 file, linenum, args[cur_arg]);
5463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
5465 }
5466
5467 tcpcheck->comment = strdup(args[cur_arg + 1]);
5468
5469 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005470 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5471 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005472 }
5473 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005474 const char *ptr_arg;
5475 int cur_arg;
5476 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005477
5478 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005479 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5480 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5481 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5482 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5483 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005484
Willy Tarreau5581c272015-05-13 12:24:53 +02005485 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5486 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5487 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5488 file, linenum);
5489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005491 }
5492
5493 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005494 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005495 tcpcheck->action = TCPCHK_ACT_CONNECT;
5496
5497 /* parsing each parameters to fill up the rule */
5498 while (*(ptr_arg = args[cur_arg])) {
5499 /* tcp port */
5500 if (strcmp(args[cur_arg], "port") == 0) {
5501 if ( (atol(args[cur_arg + 1]) > 65535) ||
5502 (atol(args[cur_arg + 1]) < 1) ){
5503 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5504 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
5507 }
5508 tcpcheck->port = atol(args[cur_arg + 1]);
5509 cur_arg += 2;
5510 }
5511 /* send proxy protocol */
5512 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5513 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5514 cur_arg++;
5515 }
5516#ifdef USE_OPENSSL
5517 else if (strcmp(args[cur_arg], "ssl") == 0) {
5518 curproxy->options |= PR_O_TCPCHK_SSL;
5519 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5520 cur_arg++;
5521 }
5522#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005523 /* comment for this tcpcheck line */
5524 else if (strcmp(args[cur_arg], "comment") == 0) {
5525 if (!*args[cur_arg + 1]) {
5526 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5527 file, linenum, args[cur_arg]);
5528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
5530 }
5531 tcpcheck->comment = strdup(args[cur_arg + 1]);
5532 cur_arg += 2;
5533 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005534 else {
5535#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005536 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 +01005537#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005538 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 +01005539#endif /* USE_OPENSSL */
5540 file, linenum, args[0], args[1], args[cur_arg]);
5541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
5544
5545 }
5546
5547 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5548 }
5549 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005550 if (! *(args[2]) ) {
5551 /* SEND string expected */
5552 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5553 file, linenum, args[0], args[1], args[2]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 } else {
5557 struct tcpcheck_rule *tcpcheck;
5558
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005559 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005560
5561 tcpcheck->action = TCPCHK_ACT_SEND;
5562 tcpcheck->string_len = strlen(args[2]);
5563 tcpcheck->string = strdup(args[2]);
5564 tcpcheck->expect_regex = NULL;
5565
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005566 /* comment for this tcpcheck line */
5567 if (strcmp(args[3], "comment") == 0) {
5568 if (!*args[4]) {
5569 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5570 file, linenum, args[3]);
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
5573 }
5574 tcpcheck->comment = strdup(args[4]);
5575 }
5576
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005577 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5578 }
5579 }
5580 else if (strcmp(args[1], "send-binary") == 0) {
5581 if (! *(args[2]) ) {
5582 /* SEND binary string expected */
5583 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5584 file, linenum, args[0], args[1], args[2]);
5585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
5587 } else {
5588 struct tcpcheck_rule *tcpcheck;
5589 char *err = NULL;
5590
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005591 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005592
5593 tcpcheck->action = TCPCHK_ACT_SEND;
5594 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5595 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5596 file, linenum, args[0], args[1], args[2], err);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600 tcpcheck->expect_regex = NULL;
5601
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005602 /* comment for this tcpcheck line */
5603 if (strcmp(args[3], "comment") == 0) {
5604 if (!*args[4]) {
5605 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5606 file, linenum, args[3]);
5607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
5609 }
5610 tcpcheck->comment = strdup(args[4]);
5611 }
5612
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005613 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5614 }
5615 }
5616 else if (strcmp(args[1], "expect") == 0) {
5617 const char *ptr_arg;
5618 int cur_arg;
5619 int inverse = 0;
5620
5621 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5622 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
5626
5627 cur_arg = 2;
5628 /* consider exclamation marks, sole or at the beginning of a word */
5629 while (*(ptr_arg = args[cur_arg])) {
5630 while (*ptr_arg == '!') {
5631 inverse = !inverse;
5632 ptr_arg++;
5633 }
5634 if (*ptr_arg)
5635 break;
5636 cur_arg++;
5637 }
5638 /* now ptr_arg points to the beginning of a word past any possible
5639 * exclamation mark, and cur_arg is the argument which holds this word.
5640 */
5641 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005642 struct tcpcheck_rule *tcpcheck;
5643 char *err = NULL;
5644
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005645 if (!*(args[cur_arg + 1])) {
5646 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5647 file, linenum, args[0], args[1], ptr_arg);
5648 err_code |= ERR_ALERT | ERR_FATAL;
5649 goto out;
5650 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005651
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005652 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005653
5654 tcpcheck->action = TCPCHK_ACT_EXPECT;
5655 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5656 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5657 file, linenum, args[0], args[1], args[2], err);
5658 err_code |= ERR_ALERT | ERR_FATAL;
5659 goto out;
5660 }
5661 tcpcheck->expect_regex = NULL;
5662 tcpcheck->inverse = inverse;
5663
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005664 /* tcpcheck comment */
5665 cur_arg += 2;
5666 if (strcmp(args[cur_arg], "comment") == 0) {
5667 if (!*args[cur_arg + 1]) {
5668 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5669 file, linenum, args[cur_arg + 1]);
5670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
5672 }
5673 tcpcheck->comment = strdup(args[cur_arg + 1]);
5674 }
5675
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005676 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5677 }
5678 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005679 struct tcpcheck_rule *tcpcheck;
5680
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005681 if (!*(args[cur_arg + 1])) {
5682 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5683 file, linenum, args[0], args[1], ptr_arg);
5684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005687
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005688 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005689
5690 tcpcheck->action = TCPCHK_ACT_EXPECT;
5691 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5692 tcpcheck->string = strdup(args[cur_arg + 1]);
5693 tcpcheck->expect_regex = NULL;
5694 tcpcheck->inverse = inverse;
5695
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005696 /* tcpcheck comment */
5697 cur_arg += 2;
5698 if (strcmp(args[cur_arg], "comment") == 0) {
5699 if (!*args[cur_arg + 1]) {
5700 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5701 file, linenum, args[cur_arg + 1]);
5702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
5705 tcpcheck->comment = strdup(args[cur_arg + 1]);
5706 }
5707
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005708 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5709 }
5710 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005711 struct tcpcheck_rule *tcpcheck;
5712
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005713 if (!*(args[cur_arg + 1])) {
5714 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5715 file, linenum, args[0], args[1], ptr_arg);
5716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
5718 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005719
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005720 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005721
5722 tcpcheck->action = TCPCHK_ACT_EXPECT;
5723 tcpcheck->string_len = 0;
5724 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005725 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5726 error = NULL;
5727 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5728 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5729 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5730 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
5733 }
5734 tcpcheck->inverse = inverse;
5735
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005736 /* tcpcheck comment */
5737 cur_arg += 2;
5738 if (strcmp(args[cur_arg], "comment") == 0) {
5739 if (!*args[cur_arg + 1]) {
5740 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5741 file, linenum, args[cur_arg + 1]);
5742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
5744 }
5745 tcpcheck->comment = strdup(args[cur_arg + 1]);
5746 }
5747
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005748 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5749 }
5750 else {
5751 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5752 file, linenum, args[0], args[1], ptr_arg);
5753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
5755 }
5756 }
5757 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005758 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005759 err_code |= ERR_ALERT | ERR_FATAL;
5760 goto out;
5761 }
5762 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005763 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005764 if (curproxy == &defproxy) {
5765 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005768 }
5769
Willy Tarreaub80c2302007-11-30 20:51:32 +01005770 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005771 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005772
5773 if (strcmp(args[1], "fail") == 0) {
5774 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005775 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005776 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5777 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005778 err_code |= ERR_ALERT | ERR_FATAL;
5779 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005780 }
5781
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005782 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005783 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5784 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005787 }
5788 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5789 }
5790 else {
5791 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005794 }
5795 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796#ifdef TPROXY
5797 else if (!strcmp(args[0], "transparent")) {
5798 /* enable transparent proxy connections */
5799 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005800 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
5803#endif
5804 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005805 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005806 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005807
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 if (*(args[1]) == 0) {
5809 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005810 err_code |= ERR_ALERT | ERR_FATAL;
5811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 }
5813 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005814 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005817 else if (!strcmp(args[0], "backlog")) { /* backlog */
5818 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005819 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005820
5821 if (*(args[1]) == 0) {
5822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005825 }
5826 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005827 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5828 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005829 }
Willy Tarreau86034312006-12-29 00:10:33 +01005830 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005831 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005832 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005833
Willy Tarreau86034312006-12-29 00:10:33 +01005834 if (*(args[1]) == 0) {
5835 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005838 }
5839 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005840 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5841 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5844 if (*(args[1]) == 0) {
5845 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005849 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5850 if (err) {
5851 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5852 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005853 err_code |= ERR_ALERT | ERR_FATAL;
5854 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005855 }
5856 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005857 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
5860 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005861 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005862 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005863 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005864
Willy Tarreaubaaee002006-06-26 02:48:02 +02005865 if (curproxy == &defproxy) {
5866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005870 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005871 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005872
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005873 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005874 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005875 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005876 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005877 goto out;
5878 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005879
5880 proto = protocol_by_family(sk->ss_family);
5881 if (!proto || !proto->connect) {
5882 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5883 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005884 err_code |= ERR_ALERT | ERR_FATAL;
5885 goto out;
5886 }
5887
5888 if (port1 != port2) {
5889 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5890 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005893 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005894
5895 if (!port1) {
5896 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5897 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005898 err_code |= ERR_ALERT | ERR_FATAL;
5899 goto out;
5900 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005901
William Lallemanddf1425a2015-04-28 20:17:49 +02005902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5903 goto out;
5904
Willy Tarreaud5191e72010-02-09 20:50:45 +01005905 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005906 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 }
5908 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005909 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005910 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005911
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005912 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5913 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005918 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005919 /**
5920 * The syntax for hash-type config element is
5921 * hash-type {map-based|consistent} [[<algo>] avalanche]
5922 *
5923 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5924 */
5925 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005926
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005927 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5928 err_code |= ERR_WARN;
5929
5930 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005931 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5932 }
5933 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005934 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5935 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005936 else if (strcmp(args[1], "avalanche") == 0) {
5937 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]);
5938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005940 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005941 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005942 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005943 err_code |= ERR_ALERT | ERR_FATAL;
5944 goto out;
5945 }
Bhaskar98634f02013-10-29 23:30:51 -04005946
5947 /* set the hash function to use */
5948 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005949 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005950 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005951
5952 /* if consistent with no argument, then avalanche modifier is also applied */
5953 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5954 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005955 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005956 /* set the hash function */
5957 if (!strcmp(args[2], "sdbm")) {
5958 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5959 }
5960 else if (!strcmp(args[2], "djb2")) {
5961 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005962 }
5963 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005964 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005965 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005966 else if (!strcmp(args[2], "crc32")) {
5967 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5968 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005969 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005970 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 -05005971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
5973 }
5974
5975 /* set the hash modifier */
5976 if (!strcmp(args[3], "avalanche")) {
5977 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5978 }
5979 else if (*args[3]) {
5980 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5981 err_code |= ERR_ALERT | ERR_FATAL;
5982 goto out;
5983 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005984 }
William Lallemanda73203e2012-03-12 12:48:57 +01005985 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005986 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5987 if (*(args[1]) == 0) {
5988 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5989 err_code |= ERR_ALERT | ERR_FATAL;
5990 goto out;
5991 }
5992 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5993 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5994 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5995 err_code |= ERR_ALERT | ERR_FATAL;
5996 goto out;
5997 }
5998 }
William Lallemanda73203e2012-03-12 12:48:57 +01005999 else if (strcmp(args[0], "unique-id-format") == 0) {
6000 if (!*(args[1])) {
6001 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6002 err_code |= ERR_ALERT | ERR_FATAL;
6003 goto out;
6004 }
William Lallemand3203ff42012-11-11 17:30:56 +01006005 if (*(args[2])) {
6006 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
6009 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006010 free(curproxy->conf.uniqueid_format_string);
6011 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006012
Willy Tarreau62a61232013-04-12 18:13:46 +02006013 free(curproxy->conf.uif_file);
6014 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6015 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006016 }
William Lallemanda73203e2012-03-12 12:48:57 +01006017
6018 else if (strcmp(args[0], "unique-id-header") == 0) {
6019 if (!*(args[1])) {
6020 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
6023 }
6024 free(curproxy->header_unique_id);
6025 curproxy->header_unique_id = strdup(args[1]);
6026 }
6027
William Lallemand723b73a2012-02-08 16:37:49 +01006028 else if (strcmp(args[0], "log-format") == 0) {
6029 if (!*(args[1])) {
6030 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6031 err_code |= ERR_ALERT | ERR_FATAL;
6032 goto out;
6033 }
William Lallemand3203ff42012-11-11 17:30:56 +01006034 if (*(args[2])) {
6035 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6036 err_code |= ERR_ALERT | ERR_FATAL;
6037 goto out;
6038 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006039 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
6040 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02006041
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006042 if (curproxy->conf.logformat_string == default_http_log_format)
6043 oldlogformat = "option httplog";
6044 else if (curproxy->conf.logformat_string == default_tcp_log_format)
6045 oldlogformat = "option tcplog";
6046 else if (curproxy->conf.logformat_string == clf_http_log_format)
6047 oldlogformat = "option httplog clf";
6048 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
6049 file, linenum, oldlogformat);
6050 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006051 if (curproxy->conf.logformat_string != default_http_log_format &&
6052 curproxy->conf.logformat_string != default_tcp_log_format &&
6053 curproxy->conf.logformat_string != clf_http_log_format)
6054 free(curproxy->conf.logformat_string);
6055 curproxy->conf.logformat_string = strdup(args[1]);
6056
6057 free(curproxy->conf.lfs_file);
6058 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6059 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006060
6061 /* get a chance to improve log-format error reporting by
6062 * reporting the correct line-number when possible.
6063 */
6064 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6065 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6066 file, linenum, curproxy->id);
6067 err_code |= ERR_WARN;
6068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006070 else if (!strcmp(args[0], "log-format-sd")) {
6071 if (!*(args[1])) {
6072 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6073 err_code |= ERR_ALERT | ERR_FATAL;
6074 goto out;
6075 }
6076 if (*(args[2])) {
6077 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6078 err_code |= ERR_ALERT | ERR_FATAL;
6079 goto out;
6080 }
6081
6082 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6083 free(curproxy->conf.logformat_sd_string);
6084 curproxy->conf.logformat_sd_string = strdup(args[1]);
6085
6086 free(curproxy->conf.lfsd_file);
6087 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6088 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6089
6090 /* get a chance to improve log-format-sd error reporting by
6091 * reporting the correct line-number when possible.
6092 */
6093 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6094 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6095 file, linenum, curproxy->id);
6096 err_code |= ERR_WARN;
6097 }
6098 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006099 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6100 if (*(args[1]) == 0) {
6101 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
6104 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006105 chunk_destroy(&curproxy->log_tag);
6106 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006107 }
William Lallemand0f99e342011-10-12 17:50:54 +02006108 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6109 /* delete previous herited or defined syslog servers */
6110 struct logsrv *back;
6111
6112 if (*(args[1]) != 0) {
6113 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6114 err_code |= ERR_ALERT | ERR_FATAL;
6115 goto out;
6116 }
6117
William Lallemand723b73a2012-02-08 16:37:49 +01006118 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6119 LIST_DEL(&tmplogsrv->list);
6120 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006121 }
6122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006123 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006124 struct logsrv *logsrv;
6125
Willy Tarreaubaaee002006-06-26 02:48:02 +02006126 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006127 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006128 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006129 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006130 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006131 LIST_INIT(&node->list);
6132 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 }
6135 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006136 struct sockaddr_storage *sk;
6137 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006138 int arg = 0;
6139 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006140
Vincent Bernat02779b62016-04-03 13:48:43 +02006141 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142
Willy Tarreau18324f52014-06-27 18:10:07 +02006143 /* just after the address, a length may be specified */
6144 if (strcmp(args[arg+2], "len") == 0) {
6145 len = atoi(args[arg+3]);
6146 if (len < 80 || len > 65535) {
6147 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6148 file, linenum, args[arg+3]);
6149 err_code |= ERR_ALERT | ERR_FATAL;
6150 goto out;
6151 }
6152 logsrv->maxlen = len;
6153
6154 /* skip these two args */
6155 arg += 2;
6156 }
6157 else
6158 logsrv->maxlen = MAX_SYSLOG_LEN;
6159
Christopher Faulet084aa962017-08-29 16:54:41 +02006160 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006161 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006162
Dragan Dosen1322d092015-09-22 16:05:32 +02006163 /* after the length, a format may be specified */
6164 if (strcmp(args[arg+2], "format") == 0) {
6165 logsrv->format = get_log_format(args[arg+3]);
6166 if (logsrv->format < 0) {
6167 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6168 err_code |= ERR_ALERT | ERR_FATAL;
6169 goto out;
6170 }
6171
6172 /* skip these two args */
6173 arg += 2;
6174 }
6175
William Lallemanddf1425a2015-04-28 20:17:49 +02006176 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6177 goto out;
6178
Willy Tarreau18324f52014-06-27 18:10:07 +02006179 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006180 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006181 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
6184
Willy Tarreaubaaee002006-06-26 02:48:02 +02006185 }
6186
William Lallemand0f99e342011-10-12 17:50:54 +02006187 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006188 if (*(args[arg+3])) {
6189 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006190 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006191 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006192 err_code |= ERR_ALERT | ERR_FATAL;
6193 goto out;
6194
Willy Tarreaubaaee002006-06-26 02:48:02 +02006195 }
6196 }
6197
William Lallemand0f99e342011-10-12 17:50:54 +02006198 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006199 if (*(args[arg+4])) {
6200 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006201 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006202 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006203 err_code |= ERR_ALERT | ERR_FATAL;
6204 goto out;
6205
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006206 }
6207 }
6208
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006209 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006210 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006211 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006212 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006213 goto out;
6214 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006215
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006216 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006217
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006218 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006219 if (port1 != port2) {
6220 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6221 file, linenum, args[0], args[1]);
6222 err_code |= ERR_ALERT | ERR_FATAL;
6223 goto out;
6224 }
6225
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006226 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006227 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006228 }
William Lallemand0f99e342011-10-12 17:50:54 +02006229
6230 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006231 }
6232 else {
6233 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6234 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 }
6238 }
6239 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006240 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006241 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006242 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006243 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006244
Willy Tarreau977b8e42006-12-29 14:19:17 +01006245 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006246 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006247
Willy Tarreaubaaee002006-06-26 02:48:02 +02006248 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006249 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6250 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006251 err_code |= ERR_ALERT | ERR_FATAL;
6252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006253 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006254
6255 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006256 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6257 free(curproxy->conn_src.iface_name);
6258 curproxy->conn_src.iface_name = NULL;
6259 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006260
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006261 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006262 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006263 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006264 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006265 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006266 goto out;
6267 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006268
6269 proto = protocol_by_family(sk->ss_family);
6270 if (!proto || !proto->connect) {
6271 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006272 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006273 err_code |= ERR_ALERT | ERR_FATAL;
6274 goto out;
6275 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006276
6277 if (port1 != port2) {
6278 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6279 file, linenum, args[0], args[1]);
6280 err_code |= ERR_ALERT | ERR_FATAL;
6281 goto out;
6282 }
6283
Willy Tarreauef9a3602012-12-08 22:29:20 +01006284 curproxy->conn_src.source_addr = *sk;
6285 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006286
6287 cur_arg = 2;
6288 while (*(args[cur_arg])) {
6289 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006290#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006291 if (!*args[cur_arg + 1]) {
6292 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6293 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006294 err_code |= ERR_ALERT | ERR_FATAL;
6295 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006296 }
6297
6298 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006299 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6300 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006301 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006302 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6303 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006304 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6305 char *name, *end;
6306
6307 name = args[cur_arg+1] + 7;
6308 while (isspace(*name))
6309 name++;
6310
6311 end = name;
6312 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6313 end++;
6314
Willy Tarreauef9a3602012-12-08 22:29:20 +01006315 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6316 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6317 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6318 curproxy->conn_src.bind_hdr_len = end - name;
6319 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6320 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6321 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006322
6323 /* now look for an occurrence number */
6324 while (isspace(*end))
6325 end++;
6326 if (*end == ',') {
6327 end++;
6328 name = end;
6329 if (*end == '-')
6330 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006331 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006332 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006333 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006334 }
6335
Willy Tarreauef9a3602012-12-08 22:29:20 +01006336 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006337 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6338 " occurrences values smaller than %d.\n",
6339 file, linenum, MAX_HDR_HISTORY);
6340 err_code |= ERR_ALERT | ERR_FATAL;
6341 goto out;
6342 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006343 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006344 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006345
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006346 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006347 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006348 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006349 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006350 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006351 goto out;
6352 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006353
6354 proto = protocol_by_family(sk->ss_family);
6355 if (!proto || !proto->connect) {
6356 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6357 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006358 err_code |= ERR_ALERT | ERR_FATAL;
6359 goto out;
6360 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006361
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006362 if (port1 != port2) {
6363 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6364 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006365 err_code |= ERR_ALERT | ERR_FATAL;
6366 goto out;
6367 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006368 curproxy->conn_src.tproxy_addr = *sk;
6369 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006370 }
6371 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006372#else /* no TPROXY support */
6373 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006374 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006375 err_code |= ERR_ALERT | ERR_FATAL;
6376 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006377#endif
6378 cur_arg += 2;
6379 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006380 }
6381
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006382 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6383#ifdef SO_BINDTODEVICE
6384 if (!*args[cur_arg + 1]) {
6385 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006387 err_code |= ERR_ALERT | ERR_FATAL;
6388 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006389 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006390 free(curproxy->conn_src.iface_name);
6391 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6392 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006393 global.last_checks |= LSTCHK_NETADM;
6394#else
6395 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6396 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006397 err_code |= ERR_ALERT | ERR_FATAL;
6398 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006399#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006400 cur_arg += 2;
6401 continue;
6402 }
6403 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006404 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006405 err_code |= ERR_ALERT | ERR_FATAL;
6406 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006407 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006409 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6410 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6411 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006412 err_code |= ERR_ALERT | ERR_FATAL;
6413 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006419 err_code |= ERR_ALERT | ERR_FATAL;
6420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422
6423 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006424 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006425 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006426 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 }
6429 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006431 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006432 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006433 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 }
6436 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006437 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006438 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006439 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006440 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 }
6443 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006444 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006445 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006446 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006447 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 }
6450 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006451 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006452 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006453 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006454 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006457 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006459 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006460 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006461 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006462 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006464 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006466 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6467 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006468 err_code |= ERR_ALERT | ERR_FATAL;
6469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471
6472 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006473 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006474 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
6478 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006480 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006481 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006482 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
6485 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006487 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006488 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 }
6492 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006494 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006495 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 }
6499 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006501 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006502 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006506 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006508 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006509 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006511 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006514 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006515
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 if (curproxy == &defproxy) {
6517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006518 err_code |= ERR_ALERT | ERR_FATAL;
6519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006521 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006522 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524 if (*(args[1]) == 0) {
6525 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006526 err_code |= ERR_ALERT | ERR_FATAL;
6527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006528 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006529
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006530 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006531 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006532 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6533 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006534 err_code |= ERR_ALERT | ERR_FATAL;
6535 goto out;
6536 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006537 err_code |= warnif_cond_conflicts(cond,
6538 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6539 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006540 }
6541 else if (*args[2]) {
6542 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6543 file, linenum, args[0], args[2]);
6544 err_code |= ERR_ALERT | ERR_FATAL;
6545 goto out;
6546 }
6547
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006548 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006549 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006550 wl->s = strdup(args[1]);
6551 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006552 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 }
6554 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006555 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006558 err_code |= ERR_ALERT | ERR_FATAL;
6559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006560 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006561
Willy Tarreauade5ec42010-01-28 19:33:49 +01006562 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006563 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006564 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006565 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006567 }
6568 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006569 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006570 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006571 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006572 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006574 }
6575 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006576 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006577 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006578 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006579 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 }
6582 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006583 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6585 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006586 err_code |= ERR_ALERT | ERR_FATAL;
6587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
6589
Willy Tarreauade5ec42010-01-28 19:33:49 +01006590 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006591 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006592 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006593 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595 }
6596 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006597 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006598 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006599 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006600 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 }
6603 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006604 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006605 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006606 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006607 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
6610 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006611 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006612
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 if (curproxy == &defproxy) {
6614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006615 err_code |= ERR_ALERT | ERR_FATAL;
6616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006618 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006619 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006620
Willy Tarreaubaaee002006-06-26 02:48:02 +02006621 if (*(args[1]) == 0) {
6622 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006623 err_code |= ERR_ALERT | ERR_FATAL;
6624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006625 }
6626
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006627 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006628 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006629 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6630 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006631 err_code |= ERR_ALERT | ERR_FATAL;
6632 goto out;
6633 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006634 err_code |= warnif_cond_conflicts(cond,
6635 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6636 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006637 }
6638 else if (*args[2]) {
6639 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6640 file, linenum, args[0], args[2]);
6641 err_code |= ERR_ALERT | ERR_FATAL;
6642 goto out;
6643 }
6644
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006645 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006646 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006647 wl->s = strdup(args[1]);
6648 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006649 }
6650 else if (!strcmp(args[0], "errorloc") ||
6651 !strcmp(args[0], "errorloc302") ||
6652 !strcmp(args[0], "errorloc303")) { /* error location */
6653 int errnum, errlen;
6654 char *err;
6655
Willy Tarreau977b8e42006-12-29 14:19:17 +01006656 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006657 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006658
Willy Tarreaubaaee002006-06-26 02:48:02 +02006659 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006660 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006661 err_code |= ERR_ALERT | ERR_FATAL;
6662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006663 }
6664
6665 errnum = atol(args[1]);
6666 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006667 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6668 err = malloc(errlen);
6669 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006670 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006671 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6672 err = malloc(errlen);
6673 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006674 }
6675
Willy Tarreau0f772532006-12-23 20:51:41 +01006676 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6677 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006678 chunk_destroy(&curproxy->errmsg[rc]);
6679 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006680 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006682 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006683
6684 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006685 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6686 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006687 free(err);
6688 }
6689 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006690 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6691 int errnum, errlen, fd;
6692 char *err;
6693 struct stat stat;
6694
6695 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006696 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006697
6698 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006699 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006700 err_code |= ERR_ALERT | ERR_FATAL;
6701 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006702 }
6703
6704 fd = open(args[2], O_RDONLY);
6705 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6706 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6707 file, linenum, args[2], args[1]);
6708 if (fd >= 0)
6709 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006710 err_code |= ERR_ALERT | ERR_FATAL;
6711 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006712 }
6713
Willy Tarreau27a674e2009-08-17 07:23:33 +02006714 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006715 errlen = stat.st_size;
6716 } else {
6717 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006718 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006719 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006720 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006721 }
6722
6723 err = malloc(errlen); /* malloc() must succeed during parsing */
6724 errnum = read(fd, err, errlen);
6725 if (errnum != errlen) {
6726 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6727 file, linenum, args[2], args[1]);
6728 close(fd);
6729 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006730 err_code |= ERR_ALERT | ERR_FATAL;
6731 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006732 }
6733 close(fd);
6734
6735 errnum = atol(args[1]);
6736 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6737 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006738 chunk_destroy(&curproxy->errmsg[rc]);
6739 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006740 break;
6741 }
6742 }
6743
6744 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006745 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6746 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006747 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006748 free(err);
6749 }
6750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006751 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006752 struct cfg_kw_list *kwl;
6753 int index;
6754
6755 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6756 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6757 if (kwl->kw[index].section != CFG_LISTEN)
6758 continue;
6759 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6760 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006761 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006762 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006763 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006764 err_code |= ERR_ALERT | ERR_FATAL;
6765 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006766 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006767 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006768 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006769 err_code |= ERR_WARN;
6770 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006771 }
Willy Tarreau93893792009-07-23 13:19:11 +02006772 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006773 }
6774 }
6775 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006776
Willy Tarreau6daf3432008-01-22 16:44:08 +01006777 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006778 err_code |= ERR_ALERT | ERR_FATAL;
6779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006780 }
Willy Tarreau93893792009-07-23 13:19:11 +02006781 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006782 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006783 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006784}
6785
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006786int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006787cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6788{
6789#ifdef CONFIG_HAP_NS
6790 const char *err;
6791 const char *item = args[0];
6792
6793 if (!strcmp(item, "namespace_list")) {
6794 return 0;
6795 }
6796 else if (!strcmp(item, "namespace")) {
6797 size_t idx = 1;
6798 const char *current;
6799 while (*(current = args[idx++])) {
6800 err = invalid_char(current);
6801 if (err) {
6802 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6803 file, linenum, *err, item, current);
6804 return ERR_ALERT | ERR_FATAL;
6805 }
6806
6807 if (netns_store_lookup(current, strlen(current))) {
6808 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6809 file, linenum, current);
6810 return ERR_ALERT | ERR_FATAL;
6811 }
6812 if (!netns_store_insert(current)) {
6813 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6814 file, linenum, current);
6815 return ERR_ALERT | ERR_FATAL;
6816 }
6817 }
6818 }
6819
6820 return 0;
6821#else
6822 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6823 file, linenum);
6824 return ERR_ALERT | ERR_FATAL;
6825#endif
6826}
6827
6828int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006829cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6830{
6831
6832 int err_code = 0;
6833 const char *err;
6834
6835 if (!strcmp(args[0], "userlist")) { /* new userlist */
6836 struct userlist *newul;
6837
6838 if (!*args[1]) {
6839 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6840 file, linenum, args[0]);
6841 err_code |= ERR_ALERT | ERR_FATAL;
6842 goto out;
6843 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006844 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6845 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006846
6847 err = invalid_char(args[1]);
6848 if (err) {
6849 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6850 file, linenum, *err, args[0], args[1]);
6851 err_code |= ERR_ALERT | ERR_FATAL;
6852 goto out;
6853 }
6854
6855 for (newul = userlist; newul; newul = newul->next)
6856 if (!strcmp(newul->name, args[1])) {
6857 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6858 file, linenum, args[1]);
6859 err_code |= ERR_WARN;
6860 goto out;
6861 }
6862
Vincent Bernat02779b62016-04-03 13:48:43 +02006863 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006864 if (!newul) {
6865 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6866 err_code |= ERR_ALERT | ERR_ABORT;
6867 goto out;
6868 }
6869
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006870 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006871 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006872 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6873 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006874 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006875 goto out;
6876 }
6877
6878 newul->next = userlist;
6879 userlist = newul;
6880
6881 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006882 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006883 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006884 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006885
6886 if (!*args[1]) {
6887 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6888 file, linenum, args[0]);
6889 err_code |= ERR_ALERT | ERR_FATAL;
6890 goto out;
6891 }
6892
6893 err = invalid_char(args[1]);
6894 if (err) {
6895 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6896 file, linenum, *err, args[0], args[1]);
6897 err_code |= ERR_ALERT | ERR_FATAL;
6898 goto out;
6899 }
6900
William Lallemand4ac9f542015-05-28 18:03:51 +02006901 if (!userlist)
6902 goto out;
6903
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006904 for (ag = userlist->groups; ag; ag = ag->next)
6905 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006906 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6907 file, linenum, args[1], userlist->name);
6908 err_code |= ERR_ALERT;
6909 goto out;
6910 }
6911
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006912 ag = calloc(1, sizeof(*ag));
6913 if (!ag) {
6914 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6915 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006916 goto out;
6917 }
6918
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006919 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006920 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006921 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6922 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006923 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006924 goto out;
6925 }
6926
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006927 cur_arg = 2;
6928
6929 while (*args[cur_arg]) {
6930 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006931 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006932 cur_arg += 2;
6933 continue;
6934 } else {
6935 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6936 file, linenum, args[0]);
6937 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006938 free(ag->groupusers);
6939 free(ag->name);
6940 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006941 goto out;
6942 }
6943 }
6944
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006945 ag->next = userlist->groups;
6946 userlist->groups = ag;
6947
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006948 } else if (!strcmp(args[0], "user")) { /* new user */
6949 struct auth_users *newuser;
6950 int cur_arg;
6951
6952 if (!*args[1]) {
6953 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6954 file, linenum, args[0]);
6955 err_code |= ERR_ALERT | ERR_FATAL;
6956 goto out;
6957 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006958 if (!userlist)
6959 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006960
6961 for (newuser = userlist->users; newuser; newuser = newuser->next)
6962 if (!strcmp(newuser->user, args[1])) {
6963 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6964 file, linenum, args[1], userlist->name);
6965 err_code |= ERR_ALERT;
6966 goto out;
6967 }
6968
Vincent Bernat02779b62016-04-03 13:48:43 +02006969 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006970 if (!newuser) {
6971 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6972 err_code |= ERR_ALERT | ERR_ABORT;
6973 goto out;
6974 }
6975
6976 newuser->user = strdup(args[1]);
6977
6978 newuser->next = userlist->users;
6979 userlist->users = newuser;
6980
6981 cur_arg = 2;
6982
6983 while (*args[cur_arg]) {
6984 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006985#ifdef CONFIG_HAP_CRYPT
6986 if (!crypt("", args[cur_arg + 1])) {
6987 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6988 file, linenum, newuser->user);
6989 err_code |= ERR_ALERT | ERR_FATAL;
6990 goto out;
6991 }
6992#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006993 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6994 file, linenum);
6995 err_code |= ERR_ALERT;
6996#endif
6997 newuser->pass = strdup(args[cur_arg + 1]);
6998 cur_arg += 2;
6999 continue;
7000 } else if (!strcmp(args[cur_arg], "insecure-password")) {
7001 newuser->pass = strdup(args[cur_arg + 1]);
7002 newuser->flags |= AU_O_INSECURE;
7003 cur_arg += 2;
7004 continue;
7005 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007006 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007007 cur_arg += 2;
7008 continue;
7009 } else {
7010 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7011 file, linenum, args[0]);
7012 err_code |= ERR_ALERT | ERR_FATAL;
7013 goto out;
7014 }
7015 }
7016 } else {
7017 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7018 err_code |= ERR_ALERT | ERR_FATAL;
7019 }
7020
7021out:
7022 return err_code;
7023}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024
Christopher Faulet79bdef32016-11-04 22:36:15 +01007025int
7026cfg_parse_scope(const char *file, int linenum, char *line)
7027{
7028 char *beg, *end, *scope = NULL;
7029 int err_code = 0;
7030 const char *err;
7031
7032 beg = line + 1;
7033 end = strchr(beg, ']');
7034
7035 /* Detect end of scope declaration */
7036 if (!end || end == beg) {
7037 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7038 file, linenum);
7039 err_code |= ERR_ALERT | ERR_FATAL;
7040 goto out;
7041 }
7042
7043 /* Get scope name and check its validity */
7044 scope = my_strndup(beg, end-beg);
7045 err = invalid_char(scope);
7046 if (err) {
7047 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7048 file, linenum, *err);
7049 err_code |= ERR_ALERT | ERR_ABORT;
7050 goto out;
7051 }
7052
7053 /* Be sure to have a scope declaration alone on its line */
7054 line = end+1;
7055 while (isspace((unsigned char)*line))
7056 line++;
7057 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7058 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7059 file, linenum, *line);
7060 err_code |= ERR_ALERT | ERR_ABORT;
7061 goto out;
7062 }
7063
7064 /* We have a valid scope declaration, save it */
7065 free(cfg_scope);
7066 cfg_scope = scope;
7067 scope = NULL;
7068
7069 out:
7070 free(scope);
7071 return err_code;
7072}
7073
Willy Tarreaubaaee002006-06-26 02:48:02 +02007074/*
7075 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007076 * Returns the error code, 0 if OK, or any combination of :
7077 * - ERR_ABORT: must abort ASAP
7078 * - ERR_FATAL: we can continue parsing but not start the service
7079 * - ERR_WARN: a warning has been emitted
7080 * - ERR_ALERT: an alert has been emitted
7081 * Only the two first ones can stop processing, the two others are just
7082 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007083 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007084int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007085{
William Lallemand64e84512015-05-12 14:25:37 +02007086 char *thisline;
7087 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088 FILE *f;
7089 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007090 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007091 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007092 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007093 int readbytes = 0;
7094
7095 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007096 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007097 return -1;
7098 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007099
David Carlier97880bb2016-04-08 10:35:26 +01007100 if ((f=fopen(file,"r")) == NULL) {
7101 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104
William Lallemandb2f07452015-05-12 14:27:13 +02007105next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007106 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007107 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007108 char *end;
7109 char *args[MAX_LINE_ARGS + 1];
7110 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007111 int dquote = 0; /* double quote */
7112 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007113
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 linenum++;
7115
7116 end = line + strlen(line);
7117
William Lallemand64e84512015-05-12 14:25:37 +02007118 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007119 /* Check if we reached the limit and the last char is not \n.
7120 * Watch out for the last line without the terminating '\n'!
7121 */
William Lallemand64e84512015-05-12 14:25:37 +02007122 char *newline;
7123 int newlinesize = linesize * 2;
7124
7125 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7126 if (newline == NULL) {
7127 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7128 file, linenum);
7129 err_code |= ERR_ALERT | ERR_FATAL;
7130 continue;
7131 }
7132
7133 readbytes = linesize - 1;
7134 linesize = newlinesize;
7135 thisline = newline;
7136 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007137 }
7138
William Lallemand64e84512015-05-12 14:25:37 +02007139 readbytes = 0;
7140
Willy Tarreaubaaee002006-06-26 02:48:02 +02007141 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007142 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007144
Christopher Faulet79bdef32016-11-04 22:36:15 +01007145
7146 if (*line == '[') {/* This is the begining if a scope */
7147 err_code |= cfg_parse_scope(file, linenum, line);
7148 goto next_line;
7149 }
7150
Willy Tarreaubaaee002006-06-26 02:48:02 +02007151 arg = 0;
7152 args[arg] = line;
7153
7154 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007155 if (*line == '"' && !squote) { /* double quote outside single quotes */
7156 if (dquote)
7157 dquote = 0;
7158 else
7159 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007160 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007161 end--;
7162 }
7163 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7164 if (squote)
7165 squote = 0;
7166 else
7167 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007168 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007169 end--;
7170 }
7171 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007172 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7173 * C equivalent value. Other combinations left unchanged (eg: \1).
7174 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007175 int skip = 0;
7176 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7177 *line = line[1];
7178 skip = 1;
7179 }
7180 else if (line[1] == 'r') {
7181 *line = '\r';
7182 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007184 else if (line[1] == 'n') {
7185 *line = '\n';
7186 skip = 1;
7187 }
7188 else if (line[1] == 't') {
7189 *line = '\t';
7190 skip = 1;
7191 }
7192 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007193 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007194 unsigned char hex1, hex2;
7195 hex1 = toupper(line[2]) - '0';
7196 hex2 = toupper(line[3]) - '0';
7197 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7198 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7199 *line = (hex1<<4) + hex2;
7200 skip = 3;
7201 }
7202 else {
7203 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007204 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007205 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007206 } else if (line[1] == '"') {
7207 *line = '"';
7208 skip = 1;
7209 } else if (line[1] == '\'') {
7210 *line = '\'';
7211 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007212 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7213 *line = '$';
7214 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007215 }
7216 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007217 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007218 end -= skip;
7219 }
7220 line++;
7221 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007222 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007223 /* end of string, end of loop */
7224 *line = 0;
7225 break;
7226 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007227 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007228 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007229 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007230 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007231 line++;
7232 args[++arg] = line;
7233 }
William Lallemandb2f07452015-05-12 14:27:13 +02007234 else if (dquote && *line == '$') {
7235 /* environment variables are evaluated inside double quotes */
7236 char *var_beg;
7237 char *var_end;
7238 char save_char;
7239 char *value;
7240 int val_len;
7241 int newlinesize;
7242 int braces = 0;
7243
7244 var_beg = line + 1;
7245 var_end = var_beg;
7246
7247 if (*var_beg == '{') {
7248 var_beg++;
7249 var_end++;
7250 braces = 1;
7251 }
7252
7253 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7254 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7255 err_code |= ERR_ALERT | ERR_FATAL;
7256 goto next_line; /* skip current line */
7257 }
7258
7259 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7260 var_end++;
7261
7262 save_char = *var_end;
7263 *var_end = '\0';
7264 value = getenv(var_beg);
7265 *var_end = save_char;
7266 val_len = value ? strlen(value) : 0;
7267
7268 if (braces) {
7269 if (*var_end == '}') {
7270 var_end++;
7271 braces = 0;
7272 } else {
7273 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7274 err_code |= ERR_ALERT | ERR_FATAL;
7275 goto next_line; /* skip current line */
7276 }
7277 }
7278
7279 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7280
7281 /* if not enough space in thisline */
7282 if (newlinesize > linesize) {
7283 char *newline;
7284
7285 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7286 if (newline == NULL) {
7287 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7288 err_code |= ERR_ALERT | ERR_FATAL;
7289 goto next_line; /* slip current line */
7290 }
7291 /* recompute pointers if realloc returns a new pointer */
7292 if (newline != thisline) {
7293 int i;
7294 int diff;
7295
7296 for (i = 0; i <= arg; i++) {
7297 diff = args[i] - thisline;
7298 args[i] = newline + diff;
7299 }
7300
7301 diff = var_end - thisline;
7302 var_end = newline + diff;
7303 diff = end - thisline;
7304 end = newline + diff;
7305 diff = line - thisline;
7306 line = newline + diff;
7307 thisline = newline;
7308 }
7309 linesize = newlinesize;
7310 }
7311
7312 /* insert value inside the line */
7313 memmove(line + val_len, var_end, end - var_end + 1);
7314 memcpy(line, value, val_len);
7315 end += val_len - (var_end - line);
7316 line += val_len;
7317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007318 else {
7319 line++;
7320 }
7321 }
William Lallemandb2f07452015-05-12 14:27:13 +02007322
William Lallemandf9873ba2015-05-05 17:37:14 +02007323 if (dquote) {
7324 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7325 err_code |= ERR_ALERT | ERR_FATAL;
7326 }
7327
7328 if (squote) {
7329 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7330 err_code |= ERR_ALERT | ERR_FATAL;
7331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007332
7333 /* empty line */
7334 if (!**args)
7335 continue;
7336
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007337 if (*line) {
7338 /* we had to stop due to too many args.
7339 * Let's terminate the string, print the offending part then cut the
7340 * last arg.
7341 */
7342 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7343 line++;
7344 *line = '\0';
7345
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007346 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007347 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007348 err_code |= ERR_ALERT | ERR_FATAL;
7349 args[arg] = line;
7350 }
7351
Willy Tarreau540abe42007-05-02 20:50:16 +02007352 /* zero out remaining args and ensure that at least one entry
7353 * is zeroed out.
7354 */
7355 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007356 args[arg] = line;
7357 }
7358
Willy Tarreau3842f002009-06-14 11:39:52 +02007359 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007360 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007361 char *tmp;
7362
Willy Tarreau3842f002009-06-14 11:39:52 +02007363 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007364 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007365 for (arg=0; *args[arg+1]; arg++)
7366 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007367 *tmp = '\0'; // fix the next arg to \0
7368 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007369 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007370 else if (!strcmp(args[0], "default")) {
7371 kwm = KWM_DEF;
7372 for (arg=0; *args[arg+1]; arg++)
7373 args[arg] = args[arg+1]; // shift args after inversion
7374 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007375
William Lallemand0f99e342011-10-12 17:50:54 +02007376 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7377 strcmp(args[0], "log") != 0) {
7378 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007379 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007380 }
7381
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007382 /* detect section start */
7383 list_for_each_entry(ics, &sections, list) {
7384 if (strcmp(args[0], ics->section_name) == 0) {
7385 cursection = ics->section_name;
7386 cs = ics;
7387 break;
7388 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007389 }
7390
William Lallemandd2ff56d2017-10-16 11:06:50 +02007391 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007392 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007393 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007394 } else {
7395 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007396
William Lallemandd2ff56d2017-10-16 11:06:50 +02007397 if (pcs != cs && pcs && pcs->post_section_parser) {
7398 err_code |= pcs->post_section_parser();
7399 if (err_code & ERR_ABORT)
7400 goto err;
7401 }
7402
7403 err_code |= cs->section_parser(file, linenum, args, kwm);
7404 if (err_code & ERR_ABORT)
7405 goto err;
7406 }
7407 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007408 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007409
7410 if (pcs == cs && pcs && pcs->post_section_parser)
7411 err_code |= pcs->post_section_parser();
7412
7413err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007414 free(cfg_scope);
7415 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007416 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007417 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007418 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007419 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007420}
7421
Willy Tarreau64ab6072014-09-16 12:17:36 +02007422/* This function propagates processes from frontend <from> to backend <to> so
7423 * that it is always guaranteed that a backend pointed to by a frontend is
7424 * bound to all of its processes. After that, if the target is a "listen"
7425 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007426 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007427 * checked first to ensure that <to> is already bound to all processes of
7428 * <from>, there is no risk of looping and we ensure to follow the shortest
7429 * path to the destination.
7430 *
7431 * It is possible to set <to> to NULL for the first call so that the function
7432 * takes care of visiting the initial frontend in <from>.
7433 *
7434 * It is important to note that the function relies on the fact that all names
7435 * have already been resolved.
7436 */
7437void propagate_processes(struct proxy *from, struct proxy *to)
7438{
7439 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007440
7441 if (to) {
7442 /* check whether we need to go down */
7443 if (from->bind_proc &&
7444 (from->bind_proc & to->bind_proc) == from->bind_proc)
7445 return;
7446
7447 if (!from->bind_proc && !to->bind_proc)
7448 return;
7449
7450 to->bind_proc = from->bind_proc ?
7451 (to->bind_proc | from->bind_proc) : 0;
7452
7453 /* now propagate down */
7454 from = to;
7455 }
7456
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007457 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007458 return;
7459
Willy Tarreauf6b70012014-12-18 14:00:43 +01007460 if (from->state == PR_STSTOPPED)
7461 return;
7462
Willy Tarreau64ab6072014-09-16 12:17:36 +02007463 /* default_backend */
7464 if (from->defbe.be)
7465 propagate_processes(from, from->defbe.be);
7466
7467 /* use_backend */
7468 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007469 if (rule->dynamic)
7470 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007471 to = rule->be.backend;
7472 propagate_processes(from, to);
7473 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007474}
7475
Willy Tarreaubb925012009-07-23 13:36:36 +02007476/*
7477 * Returns the error code, 0 if OK, or any combination of :
7478 * - ERR_ABORT: must abort ASAP
7479 * - ERR_FATAL: we can continue parsing but not start the service
7480 * - ERR_WARN: a warning has been emitted
7481 * - ERR_ALERT: an alert has been emitted
7482 * Only the two first ones can stop processing, the two others are just
7483 * indicators.
7484 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007485int check_config_validity()
7486{
7487 int cfgerr = 0;
7488 struct proxy *curproxy = NULL;
7489 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007490 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007491 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007492 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007493 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007494 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007495
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007496 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007497 /*
7498 * Now, check for the integrity of all that we have collected.
7499 */
7500
7501 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007502 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007503
Willy Tarreau193b8c62012-11-22 00:17:38 +01007504 if (!global.tune.max_http_hdr)
7505 global.tune.max_http_hdr = MAX_HTTP_HDR;
7506
7507 if (!global.tune.cookie_len)
7508 global.tune.cookie_len = CAPTURE_LEN;
7509
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007510 if (!global.tune.requri_len)
7511 global.tune.requri_len = REQURI_LEN;
7512
Emeric Brun96fd9262017-07-05 13:33:16 +02007513 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7514
Willy Tarreau193b8c62012-11-22 00:17:38 +01007515 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7516
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007517 /* Post initialisation of the users and groups lists. */
7518 err_code = userlist_postinit();
7519 if (err_code != ERR_NONE)
7520 goto out;
7521
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007522 /* first, we will invert the proxy list order */
7523 curproxy = NULL;
7524 while (proxy) {
7525 struct proxy *next;
7526
7527 next = proxy->next;
7528 proxy->next = curproxy;
7529 curproxy = proxy;
7530 if (!next)
7531 break;
7532 proxy = next;
7533 }
7534
Willy Tarreau419ead82014-09-16 13:41:21 +02007535 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007536 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007537 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007538 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007539 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007540 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007541 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007542 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007543
Willy Tarreau050536d2012-10-04 08:47:34 +02007544 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007545 /* proxy ID not set, use automatic numbering with first
7546 * spare entry starting with next_pxid.
7547 */
7548 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7549 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7550 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007551 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007552 next_pxid++;
7553
Willy Tarreau55ea7572007-06-17 19:56:27 +02007554
Willy Tarreaubaaee002006-06-26 02:48:02 +02007555 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007556 /* ensure we don't keep listeners uselessly bound */
7557 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007558 free((void *)curproxy->table.peers.name);
7559 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007560 continue;
7561 }
7562
Willy Tarreau102df612014-05-07 23:56:38 +02007563 /* Check multi-process mode compatibility for the current proxy */
7564
7565 if (curproxy->bind_proc) {
7566 /* an explicit bind-process was specified, let's check how many
7567 * processes remain.
7568 */
David Carliere6c39412015-07-02 07:00:17 +00007569 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007570
7571 curproxy->bind_proc &= nbits(global.nbproc);
7572 if (!curproxy->bind_proc && nbproc == 1) {
7573 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);
7574 curproxy->bind_proc = 1;
7575 }
7576 else if (!curproxy->bind_proc && nbproc > 1) {
7577 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);
7578 curproxy->bind_proc = 0;
7579 }
7580 }
7581
Willy Tarreau3d209582014-05-09 17:06:11 +02007582 /* check and reduce the bind-proc of each listener */
7583 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7584 unsigned long mask;
7585
7586 if (!bind_conf->bind_proc)
7587 continue;
7588
7589 mask = nbits(global.nbproc);
7590 if (curproxy->bind_proc)
7591 mask &= curproxy->bind_proc;
7592 /* mask cannot be null here thanks to the previous checks */
7593
David Carliere6c39412015-07-02 07:00:17 +00007594 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007595 bind_conf->bind_proc &= mask;
7596
7597 if (!bind_conf->bind_proc && nbproc == 1) {
7598 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",
7599 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7600 bind_conf->bind_proc = mask & ~(mask - 1);
7601 }
7602 else if (!bind_conf->bind_proc && nbproc > 1) {
7603 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",
7604 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7605 bind_conf->bind_proc = 0;
7606 }
7607 }
7608
Willy Tarreauff01a212009-03-15 13:46:16 +01007609 switch (curproxy->mode) {
7610 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007611 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007612 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007613 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7614 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007615 cfgerr++;
7616 }
7617
7618 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007619 Warning("config : servers will be ignored for %s '%s'.\n",
7620 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007621 break;
7622
7623 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007624 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007625 break;
7626
7627 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007628 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007629 break;
7630 }
7631
Willy Tarreauf3934b82015-08-11 11:36:45 +02007632 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7633 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7634 proxy_type_str(curproxy), curproxy->id);
7635 err_code |= ERR_WARN;
7636 }
7637
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007638 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007639 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007640 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007641 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7642 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007643 cfgerr++;
7644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007645#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007646 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007647 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7648 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007649 cfgerr++;
7650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007651#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007652 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007653 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7654 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007655 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007656 }
7657 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007658 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007659 /* If no LB algo is set in a backend, and we're not in
7660 * transparent mode, dispatch mode nor proxy mode, we
7661 * want to use balance roundrobin by default.
7662 */
7663 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7664 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007665 }
7666 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007667
Willy Tarreau1620ec32011-08-06 17:05:02 +02007668 if (curproxy->options & PR_O_DISPATCH)
7669 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7670 else if (curproxy->options & PR_O_HTTP_PROXY)
7671 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7672 else if (curproxy->options & PR_O_TRANSP)
7673 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007674
Willy Tarreau1620ec32011-08-06 17:05:02 +02007675 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7676 if (curproxy->options & PR_O_DISABLE404) {
7677 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7678 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7679 err_code |= ERR_WARN;
7680 curproxy->options &= ~PR_O_DISABLE404;
7681 }
7682 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7683 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7684 "send-state", proxy_type_str(curproxy), curproxy->id);
7685 err_code |= ERR_WARN;
7686 curproxy->options &= ~PR_O2_CHK_SNDST;
7687 }
Willy Tarreauef781042010-01-27 11:53:01 +01007688 }
7689
Simon Horman98637e52014-06-20 12:30:16 +09007690 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7691 if (!global.external_check) {
7692 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7693 curproxy->id, "option external-check");
7694 cfgerr++;
7695 }
7696 if (!curproxy->check_command) {
7697 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7698 curproxy->id, "option external-check");
7699 cfgerr++;
7700 }
7701 }
7702
Simon Horman64e34162015-02-06 11:11:57 +09007703 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007704 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7705 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007706 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7707 "'email-alert myhostname', or 'email-alert to' "
7708 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007709 "to be present).\n",
7710 proxy_type_str(curproxy), curproxy->id);
7711 err_code |= ERR_WARN;
7712 free_email_alert(curproxy);
7713 }
7714 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007715 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007716 }
7717
Simon Horman98637e52014-06-20 12:30:16 +09007718 if (curproxy->check_command) {
7719 int clear = 0;
7720 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7721 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7722 "external-check command", proxy_type_str(curproxy), curproxy->id);
7723 err_code |= ERR_WARN;
7724 clear = 1;
7725 }
7726 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007727 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007728 curproxy->id, "external-check command");
7729 cfgerr++;
7730 }
7731 if (clear) {
7732 free(curproxy->check_command);
7733 curproxy->check_command = NULL;
7734 }
7735 }
7736
7737 if (curproxy->check_path) {
7738 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7739 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7740 "external-check path", proxy_type_str(curproxy), curproxy->id);
7741 err_code |= ERR_WARN;
7742 free(curproxy->check_path);
7743 curproxy->check_path = NULL;
7744 }
7745 }
7746
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007747 /* if a default backend was specified, let's find it */
7748 if (curproxy->defbe.name) {
7749 struct proxy *target;
7750
Willy Tarreauafb39922015-05-26 12:04:09 +02007751 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007752 if (!target) {
7753 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7754 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007755 cfgerr++;
7756 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007757 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7758 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007759 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007760 } else if (target->mode != curproxy->mode &&
7761 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7762
7763 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7764 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7765 curproxy->conf.file, curproxy->conf.line,
7766 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7767 target->conf.file, target->conf.line);
7768 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007769 } else {
7770 free(curproxy->defbe.name);
7771 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007772 /* Update tot_fe_maxconn for a further fullconn's computation */
7773 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007774 /* Emit a warning if this proxy also has some servers */
7775 if (curproxy->srv) {
7776 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7777 curproxy->id);
7778 err_code |= ERR_WARN;
7779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007780 }
7781 }
7782
Emeric Brun3f783572017-01-12 11:21:28 +01007783 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7784 /* Case of listen without default backend
7785 * The curproxy will be its own default backend
7786 * so we update tot_fe_maxconn for a further
7787 * fullconn's computation */
7788 curproxy->tot_fe_maxconn += curproxy->maxconn;
7789 }
7790
Willy Tarreau55ea7572007-06-17 19:56:27 +02007791 /* find the target proxy for 'use_backend' rules */
7792 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007793 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007794 struct logformat_node *node;
7795 char *pxname;
7796
7797 /* Try to parse the string as a log format expression. If the result
7798 * of the parsing is only one entry containing a simple string, then
7799 * it's a standard string corresponding to a static rule, thus the
7800 * parsing is cancelled and be.name is restored to be resolved.
7801 */
7802 pxname = rule->be.name;
7803 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007804 curproxy->conf.args.ctx = ARGC_UBK;
7805 curproxy->conf.args.file = rule->file;
7806 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007807 err = NULL;
7808 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7809 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7810 rule->file, rule->line, pxname, err);
7811 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007812 cfgerr++;
7813 continue;
7814 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007815 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7816
7817 if (!LIST_ISEMPTY(&rule->be.expr)) {
7818 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7819 rule->dynamic = 1;
7820 free(pxname);
7821 continue;
7822 }
7823 /* simple string: free the expression and fall back to static rule */
7824 free(node->arg);
7825 free(node);
7826 }
7827
7828 rule->dynamic = 0;
7829 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007830
Willy Tarreauafb39922015-05-26 12:04:09 +02007831 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007832 if (!target) {
7833 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7834 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007835 cfgerr++;
7836 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007837 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7838 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007839 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007840 } else if (target->mode != curproxy->mode &&
7841 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7842
7843 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7844 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7845 curproxy->conf.file, curproxy->conf.line,
7846 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7847 target->conf.file, target->conf.line);
7848 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007849 } else {
7850 free((void *)rule->be.name);
7851 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007852 /* For each target of switching rules, we update
7853 * their tot_fe_maxconn, except if a previous rule point
7854 * on the same backend or on the default backend */
7855 if (rule->be.backend != curproxy->defbe.be) {
7856 struct switching_rule *swrule;
7857
7858 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7859 if (rule == swrule) {
7860 target->tot_fe_maxconn += curproxy->maxconn;
7861 break;
7862 }
7863 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7864 /* there is multiple ref of this backend */
7865 break;
7866 }
7867 }
7868 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007869 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007870 }
7871
Willy Tarreau64ab6072014-09-16 12:17:36 +02007872 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007873 list_for_each_entry(srule, &curproxy->server_rules, list) {
7874 struct server *target = findserver(curproxy, srule->srv.name);
7875
7876 if (!target) {
7877 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7878 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7879 cfgerr++;
7880 continue;
7881 }
7882 free((void *)srule->srv.name);
7883 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007884 }
7885
Emeric Brunb982a3d2010-01-04 15:45:53 +01007886 /* find the target table for 'stick' rules */
7887 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7888 struct proxy *target;
7889
Emeric Brun1d33b292010-01-04 15:47:17 +01007890 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7891 if (mrule->flags & STK_IS_STORE)
7892 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7893
Emeric Brunb982a3d2010-01-04 15:45:53 +01007894 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007895 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007896 else
7897 target = curproxy;
7898
7899 if (!target) {
7900 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7901 curproxy->id, mrule->table.name);
7902 cfgerr++;
7903 }
7904 else if (target->table.size == 0) {
7905 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7906 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7907 cfgerr++;
7908 }
Willy Tarreau12785782012-04-27 21:37:17 +02007909 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7910 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007911 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7912 cfgerr++;
7913 }
7914 else {
7915 free((void *)mrule->table.name);
7916 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007917 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007918 }
7919 }
7920
7921 /* find the target table for 'store response' rules */
7922 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7923 struct proxy *target;
7924
Emeric Brun1d33b292010-01-04 15:47:17 +01007925 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7926
Emeric Brunb982a3d2010-01-04 15:45:53 +01007927 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007928 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007929 else
7930 target = curproxy;
7931
7932 if (!target) {
7933 Alert("Proxy '%s': unable to find store table '%s'.\n",
7934 curproxy->id, mrule->table.name);
7935 cfgerr++;
7936 }
7937 else if (target->table.size == 0) {
7938 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7939 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7940 cfgerr++;
7941 }
Willy Tarreau12785782012-04-27 21:37:17 +02007942 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7943 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007944 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7945 cfgerr++;
7946 }
7947 else {
7948 free((void *)mrule->table.name);
7949 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007950 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007951 }
7952 }
7953
Christopher Faulete4e830d2017-09-18 14:51:41 +02007954 /* check validity for 'tcp-request' layer 4 rules */
7955 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
7956 err = NULL;
7957 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7958 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7959 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01007960 cfgerr++;
7961 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007962 }
7963
Christopher Faulete4e830d2017-09-18 14:51:41 +02007964 /* check validity for 'tcp-request' layer 5 rules */
7965 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
7966 err = NULL;
7967 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7968 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7969 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007970 cfgerr++;
7971 }
7972 }
7973
Christopher Faulete4e830d2017-09-18 14:51:41 +02007974 /* check validity for 'tcp-request' layer 6 rules */
7975 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
7976 err = NULL;
7977 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7978 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7979 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007980 cfgerr++;
7981 }
7982 }
7983
Christopher Faulete4e830d2017-09-18 14:51:41 +02007984 /* check validity for 'http-request' layer 7 rules */
7985 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
7986 err = NULL;
7987 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7988 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7989 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007990 cfgerr++;
7991 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007992 }
7993
Christopher Faulete4e830d2017-09-18 14:51:41 +02007994 /* check validity for 'http-response' layer 7 rules */
7995 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
7996 err = NULL;
7997 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7998 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7999 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02008000 cfgerr++;
8001 }
Willy Tarreau09448f72014-06-25 18:12:15 +02008002 }
8003
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008004 /* move any "block" rules at the beginning of the http-request rules */
8005 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8006 /* insert block_rules into http_req_rules at the beginning */
8007 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8008 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8009 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8010 curproxy->http_req_rules.n = curproxy->block_rules.n;
8011 LIST_INIT(&curproxy->block_rules);
8012 }
8013
Emeric Brun32da3c42010-09-23 18:39:19 +02008014 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008015 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008016
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008017 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008018 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8019 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008020 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008021 break;
8022 }
8023 }
8024
8025 if (!curpeers) {
8026 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8027 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008028 free((void *)curproxy->table.peers.name);
8029 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008030 cfgerr++;
8031 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008032 else if (curpeers->state == PR_STSTOPPED) {
8033 /* silently disable this peers section */
8034 curproxy->table.peers.p = NULL;
8035 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008036 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008037 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8038 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008039 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008040 cfgerr++;
8041 }
8042 }
8043
Simon Horman9dc49962015-01-30 11:22:59 +09008044
8045 if (curproxy->email_alert.mailers.name) {
8046 struct mailers *curmailers = mailers;
8047
8048 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02008049 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09008050 break;
Simon Horman9dc49962015-01-30 11:22:59 +09008051 }
Simon Horman9dc49962015-01-30 11:22:59 +09008052 if (!curmailers) {
8053 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8054 curproxy->id, curproxy->email_alert.mailers.name);
8055 free_email_alert(curproxy);
8056 cfgerr++;
8057 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02008058 else {
8059 err = NULL;
8060 if (init_email_alert(curmailers, curproxy, &err)) {
8061 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8062 free(err);
8063 cfgerr++;
8064 }
8065 }
Simon Horman9dc49962015-01-30 11:22:59 +09008066 }
8067
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008068 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008069 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008070 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8071 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8072 "proxy", curproxy->id);
8073 cfgerr++;
8074 goto out_uri_auth_compat;
8075 }
8076
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008077 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008078 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008079 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008080 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008081
Willy Tarreau95fa4692010-02-01 13:05:50 +01008082 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8083 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008084
8085 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008086 uri_auth_compat_req[i++] = "realm";
8087 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8088 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008089
Willy Tarreau95fa4692010-02-01 13:05:50 +01008090 uri_auth_compat_req[i++] = "unless";
8091 uri_auth_compat_req[i++] = "{";
8092 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8093 uri_auth_compat_req[i++] = "}";
8094 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008095
Willy Tarreauff011f22011-01-06 17:51:27 +01008096 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8097 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008098 cfgerr++;
8099 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008100 }
8101
Willy Tarreauff011f22011-01-06 17:51:27 +01008102 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008103
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008104 if (curproxy->uri_auth->auth_realm) {
8105 free(curproxy->uri_auth->auth_realm);
8106 curproxy->uri_auth->auth_realm = NULL;
8107 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008108
8109 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008110 }
8111out_uri_auth_compat:
8112
Dragan Dosen43885c72015-10-01 13:18:13 +02008113 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008114 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008115 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8116 if (!curproxy->conf.logformat_sd_string) {
8117 /* set the default logformat_sd_string */
8118 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8119 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008120 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008121 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008122 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008123
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008124 /* compile the log format */
8125 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008126 if (curproxy->conf.logformat_string != default_http_log_format &&
8127 curproxy->conf.logformat_string != default_tcp_log_format &&
8128 curproxy->conf.logformat_string != clf_http_log_format)
8129 free(curproxy->conf.logformat_string);
8130 curproxy->conf.logformat_string = NULL;
8131 free(curproxy->conf.lfs_file);
8132 curproxy->conf.lfs_file = NULL;
8133 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008134
8135 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8136 free(curproxy->conf.logformat_sd_string);
8137 curproxy->conf.logformat_sd_string = NULL;
8138 free(curproxy->conf.lfsd_file);
8139 curproxy->conf.lfsd_file = NULL;
8140 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008141 }
8142
Willy Tarreau62a61232013-04-12 18:13:46 +02008143 if (curproxy->conf.logformat_string) {
8144 curproxy->conf.args.ctx = ARGC_LOG;
8145 curproxy->conf.args.file = curproxy->conf.lfs_file;
8146 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008147 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008148 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008149 SMP_VAL_FE_LOG_END, &err)) {
8150 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8151 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8152 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008153 cfgerr++;
8154 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008155 curproxy->conf.args.file = NULL;
8156 curproxy->conf.args.line = 0;
8157 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008158
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008159 if (curproxy->conf.logformat_sd_string) {
8160 curproxy->conf.args.ctx = ARGC_LOGSD;
8161 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8162 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008163 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008164 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 +01008165 SMP_VAL_FE_LOG_END, &err)) {
8166 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8167 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8168 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008169 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008170 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8171 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8172 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8173 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008174 cfgerr++;
8175 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008176 curproxy->conf.args.file = NULL;
8177 curproxy->conf.args.line = 0;
8178 }
8179
Willy Tarreau62a61232013-04-12 18:13:46 +02008180 if (curproxy->conf.uniqueid_format_string) {
8181 curproxy->conf.args.ctx = ARGC_UIF;
8182 curproxy->conf.args.file = curproxy->conf.uif_file;
8183 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008184 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008185 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 +01008186 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8187 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8188 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8189 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008190 cfgerr++;
8191 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008192 curproxy->conf.args.file = NULL;
8193 curproxy->conf.args.line = 0;
8194 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008195
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008196 /* only now we can check if some args remain unresolved.
8197 * This must be done after the users and groups resolution.
8198 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008199 cfgerr += smp_resolve_args(curproxy);
8200 if (!cfgerr)
8201 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008202
Willy Tarreau2738a142006-07-08 17:28:09 +02008203 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008204 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008205 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008206 (!curproxy->timeout.connect ||
8207 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008208 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008209 " | While not properly invalid, you will certainly encounter various problems\n"
8210 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008211 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008212 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008213 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008214 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008215
Willy Tarreau1fa31262007-12-03 00:36:16 +01008216 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8217 * We must still support older configurations, so let's find out whether those
8218 * parameters have been set or must be copied from contimeouts.
8219 */
8220 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008221 if (!curproxy->timeout.tarpit ||
8222 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008223 /* tarpit timeout not set. We search in the following order:
8224 * default.tarpit, curr.connect, default.connect.
8225 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008226 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008227 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008228 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008229 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008230 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008231 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008232 }
8233 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008234 (!curproxy->timeout.queue ||
8235 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008236 /* queue timeout not set. We search in the following order:
8237 * default.queue, curr.connect, default.connect.
8238 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008239 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008240 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008241 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008242 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008243 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008244 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008245 }
8246 }
8247
Willy Tarreau1620ec32011-08-06 17:05:02 +02008248 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008249 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008250 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008251 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008252 }
8253
Willy Tarreau215663d2014-06-13 18:30:23 +02008254 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8255 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8256 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8257 proxy_type_str(curproxy), curproxy->id);
8258 err_code |= ERR_WARN;
8259 }
8260
Willy Tarreau193b8c62012-11-22 00:17:38 +01008261 /* ensure that cookie capture length is not too large */
8262 if (curproxy->capture_len >= global.tune.cookie_len) {
8263 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8264 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8265 err_code |= ERR_WARN;
8266 curproxy->capture_len = global.tune.cookie_len - 1;
8267 }
8268
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008269 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008270 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008271 curproxy->req_cap_pool = create_pool("ptrcap",
8272 curproxy->nb_req_cap * sizeof(char *),
8273 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008274 }
8275
8276 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008277 curproxy->rsp_cap_pool = create_pool("ptrcap",
8278 curproxy->nb_rsp_cap * sizeof(char *),
8279 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008280 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008281
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008282 switch (curproxy->load_server_state_from_file) {
8283 case PR_SRV_STATE_FILE_UNSPEC:
8284 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8285 break;
8286 case PR_SRV_STATE_FILE_GLOBAL:
8287 if (!global.server_state_file) {
8288 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",
8289 curproxy->id);
8290 err_code |= ERR_WARN;
8291 }
8292 break;
8293 }
8294
Willy Tarreaubaaee002006-06-26 02:48:02 +02008295 /* first, we will invert the servers list order */
8296 newsrv = NULL;
8297 while (curproxy->srv) {
8298 struct server *next;
8299
8300 next = curproxy->srv->next;
8301 curproxy->srv->next = newsrv;
8302 newsrv = curproxy->srv;
8303 if (!next)
8304 break;
8305 curproxy->srv = next;
8306 }
8307
Willy Tarreau17edc812014-01-03 12:14:34 +01008308 /* Check that no server name conflicts. This causes trouble in the stats.
8309 * We only emit a warning for the first conflict affecting each server,
8310 * in order to avoid combinatory explosion if all servers have the same
8311 * name. We do that only for servers which do not have an explicit ID,
8312 * because these IDs were made also for distinguishing them and we don't
8313 * want to annoy people who correctly manage them.
8314 */
8315 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8316 struct server *other_srv;
8317
8318 if (newsrv->puid)
8319 continue;
8320
8321 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8322 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8323 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8324 newsrv->conf.file, newsrv->conf.line,
8325 proxy_type_str(curproxy), curproxy->id,
8326 newsrv->id, other_srv->conf.line);
8327 break;
8328 }
8329 }
8330 }
8331
Willy Tarreaudd701652010-05-25 23:03:02 +02008332 /* assign automatic UIDs to servers which don't have one yet */
8333 next_id = 1;
8334 newsrv = curproxy->srv;
8335 while (newsrv != NULL) {
8336 if (!newsrv->puid) {
8337 /* server ID not set, use automatic numbering with first
8338 * spare entry starting with next_svid.
8339 */
8340 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8341 newsrv->conf.id.key = newsrv->puid = next_id;
8342 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8343 }
8344 next_id++;
8345 newsrv = newsrv->next;
8346 }
8347
Willy Tarreau20697042007-11-15 23:26:18 +01008348 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008349 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008350
Willy Tarreau62c3be22012-01-20 13:12:32 +01008351 /*
8352 * If this server supports a maxconn parameter, it needs a dedicated
8353 * tasks to fill the emptied slots when a connection leaves.
8354 * Also, resolve deferred tracking dependency if needed.
8355 */
8356 newsrv = curproxy->srv;
8357 while (newsrv != NULL) {
8358 if (newsrv->minconn > newsrv->maxconn) {
8359 /* Only 'minconn' was specified, or it was higher than or equal
8360 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8361 * this will avoid further useless expensive computations.
8362 */
8363 newsrv->maxconn = newsrv->minconn;
8364 } else if (newsrv->maxconn && !newsrv->minconn) {
8365 /* minconn was not specified, so we set it to maxconn */
8366 newsrv->minconn = newsrv->maxconn;
8367 }
8368
Willy Tarreau17d45382016-12-22 21:16:08 +01008369 /* this will also properly set the transport layer for prod and checks */
8370 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8371 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8372 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8373 }
Emeric Brun94324a42012-10-11 14:00:19 +02008374
Willy Tarreau2f075e92013-12-03 11:11:34 +01008375 /* set the check type on the server */
8376 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8377
Willy Tarreau62c3be22012-01-20 13:12:32 +01008378 if (newsrv->trackit) {
8379 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008380 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008381 char *pname, *sname;
8382
8383 pname = newsrv->trackit;
8384 sname = strrchr(pname, '/');
8385
8386 if (sname)
8387 *sname++ = '\0';
8388 else {
8389 sname = pname;
8390 pname = NULL;
8391 }
8392
8393 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008394 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008395 if (!px) {
8396 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8397 proxy_type_str(curproxy), curproxy->id,
8398 newsrv->id, pname);
8399 cfgerr++;
8400 goto next_srv;
8401 }
8402 } else
8403 px = curproxy;
8404
8405 srv = findserver(px, sname);
8406 if (!srv) {
8407 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8408 proxy_type_str(curproxy), curproxy->id,
8409 newsrv->id, sname);
8410 cfgerr++;
8411 goto next_srv;
8412 }
8413
Willy Tarreau32091232014-05-16 13:52:00 +02008414 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8415 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8416 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008417 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008418 "tracking as it does not have any check nor agent enabled.\n",
8419 proxy_type_str(curproxy), curproxy->id,
8420 newsrv->id, px->id, srv->id);
8421 cfgerr++;
8422 goto next_srv;
8423 }
8424
8425 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8426
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008427 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008428 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8429 "belongs to a tracking chain looping back to %s/%s.\n",
8430 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008431 newsrv->id, px->id, srv->id, px->id,
8432 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008433 cfgerr++;
8434 goto next_srv;
8435 }
8436
8437 if (curproxy != px &&
8438 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8439 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8440 "tracking: disable-on-404 option inconsistency.\n",
8441 proxy_type_str(curproxy), curproxy->id,
8442 newsrv->id, px->id, srv->id);
8443 cfgerr++;
8444 goto next_srv;
8445 }
8446
Willy Tarreau62c3be22012-01-20 13:12:32 +01008447 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008448 newsrv->tracknext = srv->trackers;
8449 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008450
8451 free(newsrv->trackit);
8452 newsrv->trackit = NULL;
8453 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008454
Willy Tarreau62c3be22012-01-20 13:12:32 +01008455 next_srv:
8456 newsrv = newsrv->next;
8457 }
8458
Olivier Houchard4e694042017-03-14 20:01:29 +01008459 /*
8460 * Try to generate dynamic cookies for servers now.
8461 * It couldn't be done earlier, since at the time we parsed
8462 * the server line, we may not have known yet that we
8463 * should use dynamic cookies, or the secret key may not
8464 * have been provided yet.
8465 */
8466 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8467 newsrv = curproxy->srv;
8468 while (newsrv != NULL) {
8469 srv_set_dyncookie(newsrv);
8470 newsrv = newsrv->next;
8471 }
8472
8473 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008474 /* We have to initialize the server lookup mechanism depending
8475 * on what LB algorithm was choosen.
8476 */
8477
8478 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8479 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8480 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008481 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8482 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8483 init_server_map(curproxy);
8484 } else {
8485 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8486 fwrr_init_server_groups(curproxy);
8487 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008488 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008489
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008490 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008491 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8492 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8493 fwlc_init_server_tree(curproxy);
8494 } else {
8495 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8496 fas_init_server_tree(curproxy);
8497 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008498 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008499
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008500 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008501 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8502 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8503 chash_init_server_tree(curproxy);
8504 } else {
8505 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8506 init_server_map(curproxy);
8507 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008508 break;
8509 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008510 HA_SPIN_INIT(&curproxy->lbprm.lock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02008511
8512 if (curproxy->options & PR_O_LOGASAP)
8513 curproxy->to_log &= ~LW_BYTES;
8514
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008515 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008516 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8517 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008518 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8519 proxy_type_str(curproxy), curproxy->id);
8520 err_code |= ERR_WARN;
8521 }
8522
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008523 if (curproxy->mode != PR_MODE_HTTP) {
8524 int optnum;
8525
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008526 if (curproxy->uri_auth) {
8527 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8528 proxy_type_str(curproxy), curproxy->id);
8529 err_code |= ERR_WARN;
8530 curproxy->uri_auth = NULL;
8531 }
8532
Willy Tarreaude7dc882017-03-10 11:49:21 +01008533 if (curproxy->capture_name) {
8534 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8535 proxy_type_str(curproxy), curproxy->id);
8536 err_code |= ERR_WARN;
8537 }
8538
8539 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8540 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8541 proxy_type_str(curproxy), curproxy->id);
8542 err_code |= ERR_WARN;
8543 }
8544
8545 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8546 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8547 proxy_type_str(curproxy), curproxy->id);
8548 err_code |= ERR_WARN;
8549 }
8550
8551 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8552 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8553 proxy_type_str(curproxy), curproxy->id);
8554 err_code |= ERR_WARN;
8555 }
8556
8557 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8558 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8559 proxy_type_str(curproxy), curproxy->id);
8560 err_code |= ERR_WARN;
8561 }
8562
Willy Tarreau87cf5142011-08-19 22:57:24 +02008563 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008564 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8565 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8566 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008567 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008568 }
8569
8570 if (curproxy->options & PR_O_ORGTO) {
8571 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8572 "originalto", proxy_type_str(curproxy), curproxy->id);
8573 err_code |= ERR_WARN;
8574 curproxy->options &= ~PR_O_ORGTO;
8575 }
8576
8577 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8578 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8579 (curproxy->cap & cfg_opts[optnum].cap) &&
8580 (curproxy->options & cfg_opts[optnum].val)) {
8581 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8582 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8583 err_code |= ERR_WARN;
8584 curproxy->options &= ~cfg_opts[optnum].val;
8585 }
8586 }
8587
8588 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8589 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8590 (curproxy->cap & cfg_opts2[optnum].cap) &&
8591 (curproxy->options2 & cfg_opts2[optnum].val)) {
8592 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8593 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8594 err_code |= ERR_WARN;
8595 curproxy->options2 &= ~cfg_opts2[optnum].val;
8596 }
8597 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008598
Willy Tarreau29fbe512015-08-20 19:35:14 +02008599#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008600 if (curproxy->conn_src.bind_hdr_occ) {
8601 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008602 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008603 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008604 err_code |= ERR_WARN;
8605 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008606#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008607 }
8608
Willy Tarreaubaaee002006-06-26 02:48:02 +02008609 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008610 * ensure that we're not cross-dressing a TCP server into HTTP.
8611 */
8612 newsrv = curproxy->srv;
8613 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008614 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008615 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8616 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008617 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008618 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008619
Willy Tarreau0cec3312011-10-31 13:49:26 +01008620 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8621 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8622 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8623 err_code |= ERR_WARN;
8624 }
8625
Willy Tarreauc93cd162014-05-13 15:54:22 +02008626 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008627 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8628 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8629 err_code |= ERR_WARN;
8630 }
8631
Willy Tarreau29fbe512015-08-20 19:35:14 +02008632#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008633 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8634 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008635 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 +01008636 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008637 err_code |= ERR_WARN;
8638 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008639#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008640
8641 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8642 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8643 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8644 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8645 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8646 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",
8647 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8648 err_code |= ERR_WARN;
8649 }
8650
8651
8652 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8653 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",
8654 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8655 err_code |= ERR_WARN;
8656 }
8657 }
8658
Willy Tarreau21d2af32008-02-14 20:25:24 +01008659 newsrv = newsrv->next;
8660 }
8661
Willy Tarreaue42bd962014-09-16 16:21:19 +02008662 /* check if we have a frontend with "tcp-request content" looking at L7
8663 * with no inspect-delay
8664 */
8665 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008666 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8667 if (arule->action == ACT_TCP_CAPTURE &&
8668 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008669 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008670 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8671 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008672 break;
8673 }
8674
Christopher Faulete4e830d2017-09-18 14:51:41 +02008675 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008676 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8677 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8678 " This means that these rules will randomly find their contents. This can be fixed by"
8679 " setting the tcp-request inspect-delay.\n",
8680 proxy_type_str(curproxy), curproxy->id);
8681 err_code |= ERR_WARN;
8682 }
8683 }
8684
Christopher Fauletd7c91962015-04-30 11:48:27 +02008685 /* Check filter configuration, if any */
8686 cfgerr += flt_check(curproxy);
8687
Willy Tarreauc1a21672009-08-16 22:37:44 +02008688 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008689 if (!curproxy->accept)
8690 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008691
Willy Tarreauc1a21672009-08-16 22:37:44 +02008692 if (curproxy->tcp_req.inspect_delay ||
8693 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008694 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008695
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008696 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008697 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008698 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008699 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008700
8701 /* both TCP and HTTP must check switching rules */
8702 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008703
8704 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008705 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008706 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8707 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 +01008708 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008709 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8710 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008711 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008712 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008713 }
8714
8715 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008716 if (curproxy->tcp_req.inspect_delay ||
8717 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8718 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8719
Emeric Brun97679e72010-09-23 17:56:44 +02008720 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8721 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8722
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008723 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008724 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008725 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008726 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008727
8728 /* If the backend does requires RDP cookie persistence, we have to
8729 * enable the corresponding analyser.
8730 */
8731 if (curproxy->options2 & PR_O2_RDPC_PRST)
8732 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008733
8734 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008735 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008736 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8737 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 +01008738 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008739 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8740 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008741 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008742 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008743 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008744 }
8745
8746 /***********************************************************/
8747 /* At this point, target names have already been resolved. */
8748 /***********************************************************/
8749
8750 /* Check multi-process mode compatibility */
8751
8752 if (global.nbproc > 1 && global.stats_fe) {
8753 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8754 unsigned long mask;
8755
8756 mask = nbits(global.nbproc);
8757 if (global.stats_fe->bind_proc)
8758 mask &= global.stats_fe->bind_proc;
8759
8760 if (bind_conf->bind_proc)
8761 mask &= bind_conf->bind_proc;
8762
8763 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008764 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008765 break;
8766 }
8767 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8768 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");
8769 }
8770 }
8771
8772 /* Make each frontend inherit bind-process from its listeners when not specified. */
8773 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8774 if (curproxy->bind_proc)
8775 continue;
8776
8777 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8778 unsigned long mask;
8779
Willy Tarreaue428b082015-05-04 21:57:58 +02008780 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008781 curproxy->bind_proc |= mask;
8782 }
8783
8784 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008785 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008786 }
8787
8788 if (global.stats_fe) {
8789 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8790 unsigned long mask;
8791
Cyril Bonté06181952016-02-24 00:14:54 +01008792 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008793 global.stats_fe->bind_proc |= mask;
8794 }
8795 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008796 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008797 }
8798
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008799 /* propagate bindings from frontends to backends. Don't do it if there
8800 * are any fatal errors as we must not call it with unresolved proxies.
8801 */
8802 if (!cfgerr) {
8803 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8804 if (curproxy->cap & PR_CAP_FE)
8805 propagate_processes(curproxy, NULL);
8806 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008807 }
8808
8809 /* Bind each unbound backend to all processes when not specified. */
8810 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8811 if (curproxy->bind_proc)
8812 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008813 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008814 }
8815
8816 /*******************************************************/
8817 /* At this step, all proxies have a non-null bind_proc */
8818 /*******************************************************/
8819
8820 /* perform the final checks before creating tasks */
8821
8822 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8823 struct listener *listener;
8824 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008825
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008826 /* Configure SSL for each bind line.
8827 * Note: if configuration fails at some point, the ->ctx member
8828 * remains NULL so that listeners can later detach.
8829 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008830 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008831 if (bind_conf->xprt->prepare_bind_conf &&
8832 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008833 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008834 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008835
Willy Tarreaue6b98942007-10-29 01:09:36 +01008836 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008837 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008838 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008839 int nbproc;
8840
8841 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008842 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008843 nbits(global.nbproc));
8844
8845 if (!nbproc) /* no intersection between listener and frontend */
8846 nbproc = 1;
8847
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008848 if (!listener->luid) {
8849 /* listener ID not set, use automatic numbering with first
8850 * spare entry starting with next_luid.
8851 */
8852 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8853 listener->conf.id.key = listener->luid = next_id;
8854 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008855 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008856 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008857
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008858 /* enable separate counters */
8859 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008860 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008861 if (!listener->name)
8862 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008863 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008864
Willy Tarreaue6b98942007-10-29 01:09:36 +01008865 if (curproxy->options & PR_O_TCP_NOLING)
8866 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008867 if (!listener->maxconn)
8868 listener->maxconn = curproxy->maxconn;
8869 if (!listener->backlog)
8870 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008871 if (!listener->maxaccept)
8872 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8873
8874 /* we want to have an optimal behaviour on single process mode to
8875 * maximize the work at once, but in multi-process we want to keep
8876 * some fairness between processes, so we target half of the max
8877 * number of events to be balanced over all the processes the proxy
8878 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8879 * used to disable the limit.
8880 */
8881 if (listener->maxaccept > 0) {
8882 if (nbproc > 1)
8883 listener->maxaccept = (listener->maxaccept + 1) / 2;
8884 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8885 }
8886
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008887 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008888 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008889 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008890
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008891 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008892 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008893
Willy Tarreau620408f2016-10-21 16:37:51 +02008894 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8895 listener->options |= LI_O_TCP_L5_RULES;
8896
Willy Tarreaude3041d2010-05-31 10:56:17 +02008897 if (curproxy->mon_mask.s_addr)
8898 listener->options |= LI_O_CHK_MONNET;
8899
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008900 /* smart accept mode is automatic in HTTP mode */
8901 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008902 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008903 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8904 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008905 }
8906
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008907 /* Release unused SSL configs */
8908 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008909 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8910 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008911 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008912
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008913 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008914 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008915 int count, maxproc = 0;
8916
8917 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008918 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008919 if (count > maxproc)
8920 maxproc = count;
8921 }
8922 /* backends have 0, frontends have 1 or more */
8923 if (maxproc != 1)
8924 Warning("Proxy '%s': in multi-process mode, stats will be"
8925 " limited to process assigned to the current request.\n",
8926 curproxy->id);
8927
Willy Tarreau102df612014-05-07 23:56:38 +02008928 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8929 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8930 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008931 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008932 }
Willy Tarreau102df612014-05-07 23:56:38 +02008933 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8934 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8935 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008936 }
8937 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008938
8939 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02008940 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02008941 if (curproxy->task) {
8942 curproxy->task->context = curproxy;
8943 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02008944 } else {
8945 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8946 curproxy->id);
8947 cfgerr++;
8948 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008949 }
8950
Willy Tarreaufbb78422011-06-05 15:38:35 +02008951 /* automatically compute fullconn if not set. We must not do it in the
8952 * loop above because cross-references are not yet fully resolved.
8953 */
8954 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8955 /* If <fullconn> is not set, let's set it to 10% of the sum of
8956 * the possible incoming frontend's maxconns.
8957 */
8958 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008959 /* we have the sum of the maxconns in <total>. We only
8960 * keep 10% of that sum to set the default fullconn, with
8961 * a hard minimum of 1 (to avoid a divide by zero).
8962 */
Emeric Brun3f783572017-01-12 11:21:28 +01008963 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008964 if (!curproxy->fullconn)
8965 curproxy->fullconn = 1;
8966 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008967 }
8968
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008969 /*
8970 * Recount currently required checks.
8971 */
8972
8973 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8974 int optnum;
8975
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008976 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8977 if (curproxy->options & cfg_opts[optnum].val)
8978 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008979
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008980 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8981 if (curproxy->options2 & cfg_opts2[optnum].val)
8982 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008983 }
8984
Willy Tarreau0fca4832015-05-01 19:12:05 +02008985 /* compute the required process bindings for the peers */
8986 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8987 if (curproxy->table.peers.p)
8988 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8989
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008990 if (cfg_peers) {
8991 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02008992 struct peer *p, *pb;
8993
Willy Tarreau1e273012015-05-01 19:15:17 +02008994 /* Remove all peers sections which don't have a valid listener,
8995 * which are not used by any table, or which are bound to more
8996 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008997 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008998 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02008999 while (*last) {
9000 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009001
9002 if (curpeers->state == PR_STSTOPPED) {
9003 /* the "disabled" keyword was present */
9004 if (curpeers->peers_fe)
9005 stop_proxy(curpeers->peers_fe);
9006 curpeers->peers_fe = NULL;
9007 }
9008 else if (!curpeers->peers_fe) {
9009 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9010 curpeers->id, localpeer);
9011 }
David Carliere6c39412015-07-02 07:00:17 +00009012 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009013 /* either it's totally stopped or too much used */
9014 if (curpeers->peers_fe->bind_proc) {
9015 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009016 "running in different processes (%d different ones). "
9017 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009018 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009019 cfgerr++;
9020 }
9021 stop_proxy(curpeers->peers_fe);
9022 curpeers->peers_fe = NULL;
9023 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009024 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009025 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009026 last = &curpeers->next;
9027 continue;
9028 }
9029
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009030 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009031 p = curpeers->remote;
9032 while (p) {
9033 pb = p->next;
9034 free(p->id);
9035 free(p);
9036 p = pb;
9037 }
9038
9039 /* Destroy and unlink this curpeers section.
9040 * Note: curpeers is backed up into *last.
9041 */
9042 free(curpeers->id);
9043 curpeers = curpeers->next;
9044 free(*last);
9045 *last = curpeers;
9046 }
9047 }
9048
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009049 /* initialize stick-tables on backend capable proxies. This must not
9050 * be done earlier because the data size may be discovered while parsing
9051 * other proxies.
9052 */
9053 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9054 if (curproxy->state == PR_STSTOPPED)
9055 continue;
9056
9057 if (!stktable_init(&curproxy->table)) {
9058 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9059 cfgerr++;
9060 }
9061 }
9062
Simon Horman0d16a402015-01-30 11:22:58 +09009063 if (mailers) {
9064 struct mailers *curmailers = mailers, **last;
9065 struct mailer *m, *mb;
9066
9067 /* Remove all mailers sections which don't have a valid listener.
9068 * This can happen when a mailers section is never referenced.
9069 */
9070 last = &mailers;
9071 while (*last) {
9072 curmailers = *last;
9073 if (curmailers->users) {
9074 last = &curmailers->next;
9075 continue;
9076 }
9077
9078 Warning("Removing incomplete section 'mailers %s'.\n",
9079 curmailers->id);
9080
9081 m = curmailers->mailer_list;
9082 while (m) {
9083 mb = m->next;
9084 free(m->id);
9085 free(m);
9086 m = mb;
9087 }
9088
9089 /* Destroy and unlink this curmailers section.
9090 * Note: curmailers is backed up into *last.
9091 */
9092 free(curmailers->id);
9093 curmailers = curmailers->next;
9094 free(*last);
9095 *last = curmailers;
9096 }
9097 }
9098
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009099 /* Update server_state_file_name to backend name if backend is supposed to use
9100 * a server-state file locally defined and none has been provided */
9101 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9102 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9103 curproxy->server_state_file_name == NULL)
9104 curproxy->server_state_file_name = strdup(curproxy->id);
9105 }
9106
Willy Tarreau34eb6712011-10-24 18:15:04 +02009107 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009108 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009109 MEM_F_SHARED);
9110
William Lallemand48b4bb42017-10-23 14:36:34 +02009111 list_for_each_entry(postparser, &postparsers, list) {
9112 if (postparser->func)
9113 cfgerr += postparser->func();
9114 }
9115
Willy Tarreaubb925012009-07-23 13:36:36 +02009116 if (cfgerr > 0)
9117 err_code |= ERR_ALERT | ERR_FATAL;
9118 out:
9119 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009120}
9121
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009122/*
9123 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9124 * parsing sessions.
9125 */
9126void cfg_register_keywords(struct cfg_kw_list *kwl)
9127{
9128 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9129}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009130
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009131/*
9132 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9133 */
9134void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9135{
9136 LIST_DEL(&kwl->list);
9137 LIST_INIT(&kwl->list);
9138}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009139
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009140/* this function register new section in the haproxy configuration file.
9141 * <section_name> is the name of this new section and <section_parser>
9142 * is the called parser. If two section declaration have the same name,
9143 * only the first declared is used.
9144 */
9145int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009146 int (*section_parser)(const char *, int, char **, int),
9147 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009148{
9149 struct cfg_section *cs;
9150
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009151 list_for_each_entry(cs, &sections, list) {
9152 if (strcmp(cs->section_name, section_name) == 0) {
9153 Alert("register section '%s': already registered.\n", section_name);
9154 return 0;
9155 }
9156 }
9157
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009158 cs = calloc(1, sizeof(*cs));
9159 if (!cs) {
9160 Alert("register section '%s': out of memory.\n", section_name);
9161 return 0;
9162 }
9163
9164 cs->section_name = section_name;
9165 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009166 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009167
9168 LIST_ADDQ(&sections, &cs->list);
9169
9170 return 1;
9171}
9172
William Lallemand48b4bb42017-10-23 14:36:34 +02009173/* this function register a new function which will be called once the haproxy
9174 * configuration file has been parsed. It's useful to check dependencies
9175 * between sections or to resolve items once everything is parsed.
9176 */
9177int cfg_register_postparser(char *name, int (*func)())
9178{
9179 struct cfg_postparser *cp;
9180
9181 cp = calloc(1, sizeof(*cp));
9182 if (!cp) {
9183 Alert("register postparser '%s': out of memory.\n", name);
9184 return 0;
9185 }
9186 cp->name = name;
9187 cp->func = func;
9188
9189 LIST_ADDQ(&postparsers, &cp->list);
9190
9191 return 1;
9192}
9193
Willy Tarreaubaaee002006-06-26 02:48:02 +02009194/*
David Carlier845efb52015-09-25 11:49:18 +01009195 * free all config section entries
9196 */
9197void cfg_unregister_sections(void)
9198{
9199 struct cfg_section *cs, *ics;
9200
9201 list_for_each_entry_safe(cs, ics, &sections, list) {
9202 LIST_DEL(&cs->list);
9203 free(cs);
9204 }
9205}
9206
Christopher Faulet7110b402016-10-26 11:09:44 +02009207void cfg_backup_sections(struct list *backup_sections)
9208{
9209 struct cfg_section *cs, *ics;
9210
9211 list_for_each_entry_safe(cs, ics, &sections, list) {
9212 LIST_DEL(&cs->list);
9213 LIST_ADDQ(backup_sections, &cs->list);
9214 }
9215}
9216
9217void cfg_restore_sections(struct list *backup_sections)
9218{
9219 struct cfg_section *cs, *ics;
9220
9221 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9222 LIST_DEL(&cs->list);
9223 LIST_ADDQ(&sections, &cs->list);
9224 }
9225}
9226
Willy Tarreau659fbf02016-05-26 17:55:28 +02009227__attribute__((constructor))
9228static void cfgparse_init(void)
9229{
9230 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009231 cfg_register_section("listen", cfg_parse_listen, NULL);
9232 cfg_register_section("frontend", cfg_parse_listen, NULL);
9233 cfg_register_section("backend", cfg_parse_listen, NULL);
9234 cfg_register_section("defaults", cfg_parse_listen, NULL);
9235 cfg_register_section("global", cfg_parse_global, NULL);
9236 cfg_register_section("userlist", cfg_parse_users, NULL);
9237 cfg_register_section("peers", cfg_parse_peers, NULL);
9238 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9239 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9240 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009241}
9242
David Carlier845efb52015-09-25 11:49:18 +01009243/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009244 * Local variables:
9245 * c-indent-level: 8
9246 * c-basic-offset: 8
9247 * End:
9248 */