blob: e765fdb1acabe999d5272ac629aa74db1bdaa347 [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) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200242 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100243 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
245 str = next;
246 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100247 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248 *next++ = 0;
249 }
250
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100251 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200252 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200253 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100254 if (!ss2)
255 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100257 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100258 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100260 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100263 if (!port || !end) {
264 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
265 goto fail;
266 }
267
Emeric Bruned760922010-10-22 17:59:25 +0200268 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200269 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200270 goto fail;
271 }
272
273 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200274 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200275 goto fail;
276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100278 else if (ss2->ss_family == AF_UNSPEC) {
279 socklen_t addr_len;
280
281 /* We want to attach to an already bound fd whose number
282 * is in the addr part of ss2 when cast to sockaddr_in.
283 * Note that by definition there is a single listener.
284 * We still have to determine the address family to
285 * register the correct protocol.
286 */
287 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
288 addr_len = sizeof(*ss2);
289 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
290 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
291 goto fail;
292 }
293
294 port = end = get_host_port(ss2);
295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100297 /* OK the address looks correct */
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200298 if (!create_listeners(bind_conf, ss2, port, end, fd, err)) {
299 memprintf(err, "%s for address '%s'.\n", *err, str);
300 goto fail;
301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
William Lallemand6e62fb62015-04-28 16:55:23 +0200310/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100311 * Report an error in <msg> when there are too many arguments. This version is
312 * intended to be used by keyword parsers so that the message will be included
313 * into the general error message. The index is the current keyword in args.
314 * Return 0 if the number of argument is correct, otherwise build a message and
315 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
316 * message may also be null, it will simply not be produced (useful to check only).
317 * <msg> and <err_code> are only affected on error.
318 */
319int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
320{
321 int i;
322
323 if (!*args[index + maxarg + 1])
324 return 0;
325
326 if (msg) {
327 *msg = NULL;
328 memprintf(msg, "%s", args[0]);
329 for (i = 1; i <= index; i++)
330 memprintf(msg, "%s %s", *msg, args[i]);
331
332 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
333 }
334 if (err_code)
335 *err_code |= ERR_ALERT | ERR_FATAL;
336
337 return 1;
338}
339
340/*
341 * same as too_many_args_idx with a 0 index
342 */
343int too_many_args(int maxarg, char **args, char **msg, int *err_code)
344{
345 return too_many_args_idx(maxarg, 0, args, msg, err_code);
346}
347
348/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200349 * Report a fatal Alert when there is too much arguments
350 * The index is the current keyword in args
351 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
352 * Fill err_code with an ERR_ALERT and an ERR_FATAL
353 */
354int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
355{
356 char *kw = NULL;
357 int i;
358
359 if (!*args[index + maxarg + 1])
360 return 0;
361
362 memprintf(&kw, "%s", args[0]);
363 for (i = 1; i <= index; i++) {
364 memprintf(&kw, "%s %s", kw, args[i]);
365 }
366
367 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
368 free(kw);
369 *err_code |= ERR_ALERT | ERR_FATAL;
370 return 1;
371}
372
373/*
374 * same as alertif_too_many_args_idx with a 0 index
375 */
376int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
377{
378 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
379}
380
Willy Tarreau620408f2016-10-21 16:37:51 +0200381/* Report a warning if a rule is placed after a 'tcp-request session' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
384int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
385{
386 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200394/* Report a warning if a rule is placed after a 'tcp-request content' rule.
395 * Return 1 if the warning has been emitted, otherwise 0.
396 */
397int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
398{
399 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
400 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
401 file, line, arg);
402 return 1;
403 }
404 return 0;
405}
406
Willy Tarreau61d18892009-03-31 10:49:21 +0200407/* Report a warning if a rule is placed after a 'block' rule.
408 * Return 1 if the warning has been emitted, otherwise 0.
409 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100410int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200411{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200412 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200413 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
414 file, line, arg);
415 return 1;
416 }
417 return 0;
418}
419
Willy Tarreau5002f572014-04-23 01:32:02 +0200420/* Report a warning if a rule is placed after an 'http_request' rule.
421 * Return 1 if the warning has been emitted, otherwise 0.
422 */
423int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
424{
425 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
426 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
427 file, line, arg);
428 return 1;
429 }
430 return 0;
431}
432
Willy Tarreau61d18892009-03-31 10:49:21 +0200433/* Report a warning if a rule is placed after a reqrewrite rule.
434 * Return 1 if the warning has been emitted, otherwise 0.
435 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100436int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200437{
438 if (proxy->req_exp) {
439 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
440 file, line, arg);
441 return 1;
442 }
443 return 0;
444}
445
446/* Report a warning if a rule is placed after a reqadd rule.
447 * Return 1 if the warning has been emitted, otherwise 0.
448 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100449int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200450{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100451 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200452 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
453 file, line, arg);
454 return 1;
455 }
456 return 0;
457}
458
459/* Report a warning if a rule is placed after a redirect rule.
460 * Return 1 if the warning has been emitted, otherwise 0.
461 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100462int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200463{
464 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
465 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
466 file, line, arg);
467 return 1;
468 }
469 return 0;
470}
471
472/* Report a warning if a rule is placed after a 'use_backend' rule.
473 * Return 1 if the warning has been emitted, otherwise 0.
474 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
478 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
479 file, line, arg);
480 return 1;
481 }
482 return 0;
483}
484
Willy Tarreauee445d92014-04-23 01:39:04 +0200485/* Report a warning if a rule is placed after a 'use-server' rule.
486 * Return 1 if the warning has been emitted, otherwise 0.
487 */
488int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
489{
490 if (!LIST_ISEMPTY(&proxy->server_rules)) {
491 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
492 file, line, arg);
493 return 1;
494 }
495 return 0;
496}
497
Willy Tarreaud39ad442016-11-25 15:16:12 +0100498/* report a warning if a redirect rule is dangerously placed */
499int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200500{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100501 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200502 warnif_rule_after_use_server(proxy, file, line, arg);
503}
504
Willy Tarreaud39ad442016-11-25 15:16:12 +0100505/* report a warning if a reqadd rule is dangerously placed */
506int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200507{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100508 return warnif_rule_after_redirect(proxy, file, line, arg) ||
509 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200510}
511
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512/* report a warning if a reqxxx rule is dangerously placed */
513int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200514{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
516 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200517}
518
519/* report a warning if an http-request rule is dangerously placed */
520int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
521{
Willy Tarreau61d18892009-03-31 10:49:21 +0200522 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100523 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a block rule is dangerously placed */
527int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_http_req(proxy, file, line, arg) ||
530 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200531}
532
Willy Tarreaud39ad442016-11-25 15:16:12 +0100533/* report a warning if a "tcp request content" rule is dangerously placed */
534int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200535{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100536 return warnif_rule_after_block(proxy, file, line, arg) ||
537 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200538}
539
Willy Tarreaud39ad442016-11-25 15:16:12 +0100540/* report a warning if a "tcp request session" rule is dangerously placed */
541int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200542{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100543 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
544 warnif_misplaced_tcp_cont(proxy, file, line, arg);
545}
546
547/* report a warning if a "tcp request connection" rule is dangerously placed */
548int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
549{
550 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
551 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200552}
553
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554/* Report it if a request ACL condition uses some keywords that are incompatible
555 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
556 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
557 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100558 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100560{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200562 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100563
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100564 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565 return 0;
566
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100567 acl = acl_cond_conflicts(cond, where);
568 if (acl) {
569 if (acl->name && *acl->name)
570 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
571 file, line, acl->name, sample_ckp_names(where));
572 else
573 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 +0200574 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 return ERR_WARN;
576 }
577 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100578 return 0;
579
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100580 if (acl->name && *acl->name)
581 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200582 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100583 else
584 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200585 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100586 return ERR_WARN;
587}
588
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200590 * parse a line in a <global> section. Returns the error code, 0 if OK, or
591 * any combination of :
592 * - ERR_ABORT: must abort ASAP
593 * - ERR_FATAL: we can continue parsing but not start the service
594 * - ERR_WARN: a warning has been emitted
595 * - ERR_ALERT: an alert has been emitted
596 * Only the two first ones can stop processing, the two others are just
597 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200599int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600{
Willy Tarreau058e9072009-07-20 09:30:05 +0200601 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200602 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603
604 if (!strcmp(args[0], "global")) { /* new section */
605 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200606 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200610 if (alertif_too_many_args(0, file, linenum, args, &err_code))
611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 global.mode |= MODE_DAEMON;
613 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200614 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200615 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200616 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200617 if (*args[1]) {
618 if (!strcmp(args[1], "exit-on-failure")) {
619 global.tune.options |= GTUNE_EXIT_ONFAILURE;
620 } else {
621 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200626 global.mode |= MODE_MWORKER;
627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200629 if (alertif_too_many_args(0, file, linenum, args, &err_code))
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 global.mode |= MODE_DEBUG;
632 }
633 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200634 if (alertif_too_many_args(0, file, linenum, args, &err_code))
635 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100636 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200638 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(0, file, linenum, args, &err_code))
640 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100641 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200644 if (alertif_too_many_args(0, file, linenum, args, &err_code))
645 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100646 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100648 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200649 if (alertif_too_many_args(0, file, linenum, args, &err_code))
650 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100651 global.tune.options &= ~GTUNE_USE_SPLICE;
652 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200653 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200654 if (alertif_too_many_args(0, file, linenum, args, &err_code))
655 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200656 global.tune.options &= ~GTUNE_USE_GAI;
657 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000658 else if (!strcmp(args[0], "noreuseport")) {
659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
661 global.tune.options &= ~GTUNE_USE_REUSEPORT;
662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 global.mode |= MODE_QUIET;
667 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200668 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(1, file, linenum, args, &err_code))
670 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200671 if (global.tune.maxpollevents != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200680 }
681 global.tune.maxpollevents = atol(args[1]);
682 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100683 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
685 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100686 if (global.tune.maxaccept != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100695 }
696 global.tune.maxaccept = atol(args[1]);
697 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200698 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200699 if (alertif_too_many_args(1, file, linenum, args, &err_code))
700 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200701 if (*(args[1]) == 0) {
702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
703 err_code |= ERR_ALERT | ERR_FATAL;
704 goto out;
705 }
706 global.tune.chksize = atol(args[1]);
707 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100708 else if (!strcmp(args[0], "tune.recv_enough")) {
709 if (alertif_too_many_args(1, file, linenum, args, &err_code))
710 goto out;
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 global.tune.recv_enough = atol(args[1]);
717 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100718 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
720 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100721 if (*(args[1]) == 0) {
722 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
725 }
726 global.tune.buf_limit = atol(args[1]);
727 if (global.tune.buf_limit) {
728 if (global.tune.buf_limit < 3)
729 global.tune.buf_limit = 3;
730 if (global.tune.buf_limit <= global.tune.reserved_bufs)
731 global.tune.buf_limit = global.tune.reserved_bufs + 1;
732 }
733 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100734 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200735 if (alertif_too_many_args(1, file, linenum, args, &err_code))
736 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 global.tune.reserved_bufs = atol(args[1]);
743 if (global.tune.reserved_bufs < 2)
744 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100745 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
746 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100747 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200748 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200757 if (global.tune.bufsize <= 0) {
758 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200762 }
763 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200764 if (alertif_too_many_args(1, file, linenum, args, &err_code))
765 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200772 if (global.tune.maxrewrite < 0) {
773 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
776 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200777 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100778 else if (!strcmp(args[0], "tune.idletimer")) {
779 unsigned int idle;
780 const char *res;
781
William Lallemand1a748ae2015-05-19 16:37:23 +0200782 if (alertif_too_many_args(1, file, linenum, args, &err_code))
783 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100784 if (*(args[1]) == 0) {
785 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789
790 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
791 if (res) {
792 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
793 file, linenum, *res, args[0]);
794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
796 }
797
798 if (idle > 65535) {
799 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803 global.tune.idle_timer = idle;
804 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100805 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200806 if (alertif_too_many_args(1, file, linenum, args, &err_code))
807 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100808 if (global.tune.client_rcvbuf != 0) {
809 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
810 err_code |= ERR_ALERT;
811 goto out;
812 }
813 if (*(args[1]) == 0) {
814 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 global.tune.client_rcvbuf = atol(args[1]);
819 }
820 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100823 if (global.tune.server_rcvbuf != 0) {
824 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT;
826 goto out;
827 }
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.tune.server_rcvbuf = atol(args[1]);
834 }
835 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100838 if (global.tune.client_sndbuf != 0) {
839 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT;
841 goto out;
842 }
843 if (*(args[1]) == 0) {
844 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
848 global.tune.client_sndbuf = atol(args[1]);
849 }
850 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200851 if (alertif_too_many_args(1, file, linenum, args, &err_code))
852 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100853 if (global.tune.server_sndbuf != 0) {
854 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
855 err_code |= ERR_ALERT;
856 goto out;
857 }
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 global.tune.server_sndbuf = atol(args[1]);
864 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200865 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200866 if (alertif_too_many_args(1, file, linenum, args, &err_code))
867 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200868 if (*(args[1]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873 global.tune.pipesize = atol(args[1]);
874 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100875 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200876 if (alertif_too_many_args(1, file, linenum, args, &err_code))
877 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100878 if (*(args[1]) == 0) {
879 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 global.tune.cookie_len = atol(args[1]) + 1;
884 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200885 else if (!strcmp(args[0], "tune.http.logurilen")) {
886 if (alertif_too_many_args(1, file, linenum, args, &err_code))
887 goto out;
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 global.tune.requri_len = atol(args[1]) + 1;
894 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200895 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200896 if (alertif_too_many_args(1, file, linenum, args, &err_code))
897 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200903 global.tune.max_http_hdr = atoi(args[1]);
904 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
905 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
906 file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200910 }
William Lallemandf3747832012-11-09 12:33:10 +0100911 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100914 if (*args[1]) {
915 global.tune.comp_maxlevel = atoi(args[1]);
916 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
917 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
918 file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 } else {
923 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
924 file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200929 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
930 if (*args[1]) {
931 global.tune.pattern_cache = atoi(args[1]);
932 if (global.tune.pattern_cache < 0) {
933 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
934 file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 } else {
939 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
940 file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200946 if (alertif_too_many_args(1, file, linenum, args, &err_code))
947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200949 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200950 err_code |= ERR_ALERT;
951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 }
953 if (*(args[1]) == 0) {
954 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT | ERR_FATAL;
956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100958 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
959 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]);
960 err_code |= ERR_WARN;
961 goto out;
962 }
963
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
965 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200966 if (alertif_too_many_args(1, file, linenum, args, &err_code))
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200969 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200970 err_code |= ERR_ALERT;
971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200972 }
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100978 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
979 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]);
980 err_code |= ERR_WARN;
981 goto out;
982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200983 }
Simon Horman98637e52014-06-20 12:30:16 +0900984 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(0, file, linenum, args, &err_code))
986 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900987 global.external_check = 1;
988 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200989 /* user/group name handling */
990 else if (!strcmp(args[0], "user")) {
991 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200992 if (alertif_too_many_args(1, file, linenum, args, &err_code))
993 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200994 if (global.uid != 0) {
995 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT;
997 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200998 }
999 errno = 0;
1000 ha_user = getpwnam(args[1]);
1001 if (ha_user != NULL) {
1002 global.uid = (int)ha_user->pw_uid;
1003 }
1004 else {
1005 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 +02001006 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001007 }
1008 }
1009 else if (!strcmp(args[0], "group")) {
1010 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001011 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1012 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001013 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001014 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT;
1016 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001017 }
1018 errno = 0;
1019 ha_group = getgrnam(args[1]);
1020 if (ha_group != NULL) {
1021 global.gid = (int)ha_group->gr_gid;
1022 }
1023 else {
1024 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 +02001025 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001026 }
1027 }
1028 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001030 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 if (*(args[1]) == 0) {
1033 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 }
1037 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001038 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1039 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1040 file, linenum, args[0], LONGBITS, global.nbproc);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001044 }
Christopher Fauletbe0faa22017-08-29 15:37:10 +02001045 else if (!strcmp(args[0], "nbthread")) {
1046 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1047 goto out;
1048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
1052 }
1053 global.nbthread = atol(args[1]);
1054 if (global.nbthread < 1 || global.nbthread > LONGBITS) {
1055 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1056 file, linenum, args[0], LONGBITS, global.nbthread);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
1060#ifndef USE_THREAD
1061 if (global.nbthread > 1) {
1062 Alert("HAProxy is not compiled with threads support, please check build options for USE_THREAD.\n");
1063 global.nbthread = 1;
1064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
1066 }
1067#endif
1068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001070 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 if (global.maxconn != 0) {
1073 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001074 err_code |= ERR_ALERT;
1075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 }
1077 if (*(args[1]) == 0) {
1078 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 }
1082 global.maxconn = atol(args[1]);
1083#ifdef SYSTEM_MAXCONN
1084 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1085 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);
1086 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001087 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 }
1089#endif /* SYSTEM_MAXCONN */
1090 }
Emeric Brun850efd52014-01-29 12:24:34 +01001091 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001092 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1093 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001094 if (*(args[1]) == 0) {
1095 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
1098 }
1099 if (strcmp(args[1],"none") == 0)
1100 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1101 else if (strcmp(args[1],"required") == 0)
1102 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1103 else {
1104 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1105 err_code |= ERR_ALERT | ERR_FATAL;
1106 goto out;
1107 }
1108 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001109 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1111 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001112 if (global.cps_lim != 0) {
1113 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT;
1115 goto out;
1116 }
1117 if (*(args[1]) == 0) {
1118 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto out;
1121 }
1122 global.cps_lim = atol(args[1]);
1123 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001124 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001125 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1126 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001127 if (global.sps_lim != 0) {
1128 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1129 err_code |= ERR_ALERT;
1130 goto out;
1131 }
1132 if (*(args[1]) == 0) {
1133 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto out;
1136 }
1137 global.sps_lim = atol(args[1]);
1138 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001139 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001140 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1141 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001142 if (global.ssl_lim != 0) {
1143 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1144 err_code |= ERR_ALERT;
1145 goto out;
1146 }
1147 if (*(args[1]) == 0) {
1148 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152 global.ssl_lim = atol(args[1]);
1153 }
William Lallemandd85f9172012-11-09 17:05:39 +01001154 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001155 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1156 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001157 if (*(args[1]) == 0) {
1158 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
1161 }
1162 global.comp_rate_lim = atoi(args[1]) * 1024;
1163 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001164 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001165 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1166 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001167 if (global.maxpipes != 0) {
1168 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001169 err_code |= ERR_ALERT;
1170 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001171 }
1172 if (*(args[1]) == 0) {
1173 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001176 }
1177 global.maxpipes = atol(args[1]);
1178 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001179 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001182 if (*(args[1]) == 0) {
1183 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
William Lallemande3a7d992012-11-20 11:25:20 +01001187 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001188 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001189 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001190 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1191 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001192 if (*(args[1]) == 0) {
1193 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1194 err_code |= ERR_ALERT | ERR_FATAL;
1195 goto out;
1196 }
1197 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001198 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001199 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001203 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001204
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001206 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 if (global.rlimit_nofile != 0) {
1209 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001210 err_code |= ERR_ALERT;
1211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001212 }
1213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 global.rlimit_nofile = atol(args[1]);
1219 }
1220 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001221 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 if (global.chroot != NULL) {
1224 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001225 err_code |= ERR_ALERT;
1226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227 }
1228 if (*(args[1]) == 0) {
1229 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 }
1233 global.chroot = strdup(args[1]);
1234 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001235 else if (!strcmp(args[0], "description")) {
1236 int i, len=0;
1237 char *d;
1238
1239 if (!*args[1]) {
1240 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1241 file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245
Willy Tarreau348acfe2014-04-14 15:00:39 +02001246 for (i = 1; *args[i]; i++)
1247 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001248
1249 if (global.desc)
1250 free(global.desc);
1251
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001252 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001253
Willy Tarreau348acfe2014-04-14 15:00:39 +02001254 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1255 for (i = 2; *args[i]; i++)
1256 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001257 }
1258 else if (!strcmp(args[0], "node")) {
1259 int i;
1260 char c;
1261
William Lallemand1a748ae2015-05-19 16:37:23 +02001262 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1263 goto out;
1264
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001265 for (i=0; args[1][i]; i++) {
1266 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001267 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1268 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001269 break;
1270 }
1271
1272 if (!i || args[1][i]) {
1273 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1274 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1275 file, linenum, args[0]);
1276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
1279
1280 if (global.node)
1281 free(global.node);
1282
1283 global.node = strdup(args[1]);
1284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001286 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288 if (global.pidfile != NULL) {
1289 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001290 err_code |= ERR_ALERT;
1291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 }
1293 if (*(args[1]) == 0) {
1294 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 }
1298 global.pidfile = strdup(args[1]);
1299 }
Emeric Bruned760922010-10-22 17:59:25 +02001300 else if (!strcmp(args[0], "unix-bind")) {
1301 int cur_arg = 1;
1302 while (*(args[cur_arg])) {
1303 if (!strcmp(args[cur_arg], "prefix")) {
1304 if (global.unix_bind.prefix != NULL) {
1305 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1306 err_code |= ERR_ALERT;
1307 cur_arg += 2;
1308 continue;
1309 }
1310
1311 if (*(args[cur_arg+1]) == 0) {
1312 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
1315 }
1316 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1317 cur_arg += 2;
1318 continue;
1319 }
1320
1321 if (!strcmp(args[cur_arg], "mode")) {
1322
1323 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1324 cur_arg += 2;
1325 continue;
1326 }
1327
1328 if (!strcmp(args[cur_arg], "uid")) {
1329
1330 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1331 cur_arg += 2;
1332 continue;
1333 }
1334
1335 if (!strcmp(args[cur_arg], "gid")) {
1336
1337 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1338 cur_arg += 2;
1339 continue;
1340 }
1341
1342 if (!strcmp(args[cur_arg], "user")) {
1343 struct passwd *user;
1344
1345 user = getpwnam(args[cur_arg + 1]);
1346 if (!user) {
1347 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1348 file, linenum, args[0], args[cur_arg + 1 ]);
1349 err_code |= ERR_ALERT | ERR_FATAL;
1350 goto out;
1351 }
1352
1353 global.unix_bind.ux.uid = user->pw_uid;
1354 cur_arg += 2;
1355 continue;
1356 }
1357
1358 if (!strcmp(args[cur_arg], "group")) {
1359 struct group *group;
1360
1361 group = getgrnam(args[cur_arg + 1]);
1362 if (!group) {
1363 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1364 file, linenum, args[0], args[cur_arg + 1 ]);
1365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
1367 }
1368
1369 global.unix_bind.ux.gid = group->gr_gid;
1370 cur_arg += 2;
1371 continue;
1372 }
1373
Willy Tarreaub48f9582011-09-05 01:17:06 +02001374 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001375 file, linenum, args[0]);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
1378 }
1379 }
William Lallemand0f99e342011-10-12 17:50:54 +02001380 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1381 /* delete previous herited or defined syslog servers */
1382 struct logsrv *back;
1383 struct logsrv *tmp;
1384
1385 if (*(args[1]) != 0) {
1386 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
1389 }
1390
1391 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1392 LIST_DEL(&tmp->list);
1393 free(tmp);
1394 }
1395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001397 struct sockaddr_storage *sk;
1398 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001399 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001400 int arg = 0;
1401 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001402
William Lallemand1a748ae2015-05-19 16:37:23 +02001403 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1404 goto out;
1405
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 if (*(args[1]) == 0 || *(args[2]) == 0) {
1407 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001408 err_code |= ERR_ALERT | ERR_FATAL;
1409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 }
William Lallemand0f99e342011-10-12 17:50:54 +02001411
Vincent Bernat02779b62016-04-03 13:48:43 +02001412 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001413
Willy Tarreau18324f52014-06-27 18:10:07 +02001414 /* just after the address, a length may be specified */
1415 if (strcmp(args[arg+2], "len") == 0) {
1416 len = atoi(args[arg+3]);
1417 if (len < 80 || len > 65535) {
1418 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1419 file, linenum, args[arg+3]);
1420 err_code |= ERR_ALERT | ERR_FATAL;
1421 goto out;
1422 }
1423 logsrv->maxlen = len;
1424
1425 /* skip these two args */
1426 arg += 2;
1427 }
1428 else
1429 logsrv->maxlen = MAX_SYSLOG_LEN;
1430
Christopher Faulet084aa962017-08-29 16:54:41 +02001431 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001432 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001433
Dragan Dosen1322d092015-09-22 16:05:32 +02001434 /* after the length, a format may be specified */
1435 if (strcmp(args[arg+2], "format") == 0) {
1436 logsrv->format = get_log_format(args[arg+3]);
1437 if (logsrv->format < 0) {
1438 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1439 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001440 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001441 goto out;
1442 }
1443
1444 /* skip these two args */
1445 arg += 2;
1446 }
1447
David Carlier97880bb2016-04-08 10:35:26 +01001448 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1449 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001450 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001451 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001452
Willy Tarreau18324f52014-06-27 18:10:07 +02001453 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001454 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001455 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001456 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001457 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 }
1459
William Lallemand0f99e342011-10-12 17:50:54 +02001460 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001461 if (*(args[arg+3])) {
1462 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001463 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001464 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001465 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001466 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 }
1468 }
1469
William Lallemand0f99e342011-10-12 17:50:54 +02001470 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001471 if (*(args[arg+4])) {
1472 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001473 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001474 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001475 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001476 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001477 }
1478 }
1479
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001480 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001481 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001482 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001483 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001484 free(logsrv);
1485 goto out;
1486 }
1487 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001488
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001489 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001490 if (port1 != port2) {
1491 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1492 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001493 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001494 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001495 goto out;
1496 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001497
William Lallemand0f99e342011-10-12 17:50:54 +02001498 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001499 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001500 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502
William Lallemand0f99e342011-10-12 17:50:54 +02001503 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001504 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001505 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1506 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001507
1508 if (global.log_send_hostname != NULL) {
1509 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1510 err_code |= ERR_ALERT;
1511 goto out;
1512 }
1513
1514 if (*(args[1]))
1515 name = args[1];
1516 else
1517 name = hostname;
1518
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001519 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001520 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001521 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001522 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1523 if (global.server_state_base != NULL) {
1524 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1525 err_code |= ERR_ALERT;
1526 goto out;
1527 }
1528
1529 if (!*(args[1])) {
1530 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1531 err_code |= ERR_FATAL;
1532 goto out;
1533 }
1534
1535 global.server_state_base = strdup(args[1]);
1536 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001537 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1538 if (global.server_state_file != NULL) {
1539 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1540 err_code |= ERR_ALERT;
1541 goto out;
1542 }
1543
1544 if (!*(args[1])) {
1545 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1546 err_code |= ERR_FATAL;
1547 goto out;
1548 }
1549
1550 global.server_state_file = strdup(args[1]);
1551 }
Kevinm48936af2010-12-22 16:08:21 +00001552 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001553 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1554 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001555 if (*(args[1]) == 0) {
1556 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1557 err_code |= ERR_ALERT | ERR_FATAL;
1558 goto out;
1559 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001560 chunk_destroy(&global.log_tag);
1561 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001562 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001563 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001564 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1565 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001566 if (global.spread_checks != 0) {
1567 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001568 err_code |= ERR_ALERT;
1569 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001570 }
1571 if (*(args[1]) == 0) {
1572 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001575 }
1576 global.spread_checks = atol(args[1]);
1577 if (global.spread_checks < 0 || global.spread_checks > 50) {
1578 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001579 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001582 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1583 const char *err;
1584 unsigned int val;
1585
William Lallemand1a748ae2015-05-19 16:37:23 +02001586 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1587 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001588 if (*(args[1]) == 0) {
1589 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1590 err_code |= ERR_ALERT | ERR_FATAL;
1591 goto out;
1592 }
1593
1594 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1595 if (err) {
1596 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1597 err_code |= ERR_ALERT | ERR_FATAL;
1598 }
1599 global.max_spread_checks = val;
1600 if (global.max_spread_checks < 0) {
1601 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1602 err_code |= ERR_ALERT | ERR_FATAL;
1603 }
1604 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001605 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1606#ifdef USE_CPU_AFFINITY
1607 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001608 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001609 unsigned long cpus = 0;
1610
1611 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001612 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001613 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001614 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001615 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001616 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001617 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001618 proc = atol(args[1]);
1619 if (proc >= 1 && proc <= LONGBITS)
1620 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001621 }
1622
1623 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001624 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1625 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
1629
1630 cur_arg = 2;
1631 while (*args[cur_arg]) {
1632 unsigned int low, high;
1633
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001634 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001635 char *dash = strchr(args[cur_arg], '-');
1636
1637 low = high = str2uic(args[cur_arg]);
1638 if (dash)
1639 high = str2uic(dash + 1);
1640
1641 if (high < low) {
1642 unsigned int swap = low;
1643 low = high;
1644 high = swap;
1645 }
1646
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001647 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001648 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001649 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653
1654 while (low <= high)
1655 cpus |= 1UL << low++;
1656 }
1657 else {
1658 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1659 file, linenum, args[0], args[cur_arg]);
1660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662 }
1663 cur_arg++;
1664 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001665 for (i = 0; i < LONGBITS; i++)
1666 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001667 global.cpu_map[i] = cpus;
1668#else
1669 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
1672#endif
1673 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001674 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1675 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1676 goto out;
1677
1678 if (*(args[2]) == 0) {
1679 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
1682 }
1683
1684 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1685 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1686 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
1689 }
1690 }
1691 else if (!strcmp(args[0], "unsetenv")) {
1692 int arg;
1693
1694 if (*(args[1]) == 0) {
1695 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1696 err_code |= ERR_ALERT | ERR_FATAL;
1697 goto out;
1698 }
1699
1700 for (arg = 1; *args[arg]; arg++) {
1701 if (unsetenv(args[arg]) != 0) {
1702 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
1705 }
1706 }
1707 }
1708 else if (!strcmp(args[0], "resetenv")) {
1709 extern char **environ;
1710 char **env = environ;
1711
1712 /* args contain variable names to keep, one per argument */
1713 while (*env) {
1714 int arg;
1715
1716 /* look for current variable in among all those we want to keep */
1717 for (arg = 1; *args[arg]; arg++) {
1718 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1719 (*env)[strlen(args[arg])] == '=')
1720 break;
1721 }
1722
1723 /* delete this variable */
1724 if (!*args[arg]) {
1725 char *delim = strchr(*env, '=');
1726
1727 if (!delim || delim - *env >= trash.size) {
1728 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
1731 }
1732
1733 memcpy(trash.str, *env, delim - *env);
1734 trash.str[delim - *env] = 0;
1735
1736 if (unsetenv(trash.str) != 0) {
1737 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
1740 }
1741 }
1742 else
1743 env++;
1744 }
1745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001747 struct cfg_kw_list *kwl;
1748 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001749 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001750
1751 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1752 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1753 if (kwl->kw[index].section != CFG_GLOBAL)
1754 continue;
1755 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001756 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001757 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001758 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001759 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001760 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001761 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001762 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001763 err_code |= ERR_WARN;
1764 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001765 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001766 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001767 }
1768 }
1769 }
1770
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001774
Willy Tarreau058e9072009-07-20 09:30:05 +02001775 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001776 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001777 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778}
1779
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001780void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001782 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 defproxy.mode = PR_MODE_TCP;
1784 defproxy.state = PR_STNEW;
1785 defproxy.maxconn = cfg_maxpconn;
1786 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001787 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001788 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001789
Simon Horman66183002013-02-23 10:16:43 +09001790 defproxy.defsrv.check.inter = DEF_CHKINTR;
1791 defproxy.defsrv.check.fastinter = 0;
1792 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001793 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1794 defproxy.defsrv.agent.fastinter = 0;
1795 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001796 defproxy.defsrv.check.rise = DEF_RISETIME;
1797 defproxy.defsrv.check.fall = DEF_FALLTIME;
1798 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1799 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001800 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001801 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001802 defproxy.defsrv.maxqueue = 0;
1803 defproxy.defsrv.minconn = 0;
1804 defproxy.defsrv.maxconn = 0;
1805 defproxy.defsrv.slowstart = 0;
1806 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1807 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1808 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001809
1810 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001811 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812}
1813
Willy Tarreauade5ec42010-01-28 19:33:49 +01001814
Willy Tarreau63af98d2014-05-18 08:11:41 +02001815/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1816 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1817 * ERR_FATAL in case of error.
1818 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001819static int create_cond_regex_rule(const char *file, int line,
1820 struct proxy *px, int dir, int action, int flags,
1821 const char *cmd, const char *reg, const char *repl,
1822 const char **cond_start)
1823{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001824 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001825 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001826 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001827 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001828 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001829 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001830 int cs;
1831 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001832
1833 if (px == &defproxy) {
1834 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001835 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001836 goto err;
1837 }
1838
1839 if (*reg == 0) {
1840 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001841 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001842 goto err;
1843 }
1844
Christopher Faulet898566e2016-10-26 11:06:28 +02001845 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001846 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001847
Willy Tarreau5321c422010-01-28 20:35:13 +01001848 if (cond_start &&
1849 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02001850 if ((cond = build_acl_cond(file, line, &px->acl, px, cond_start, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001851 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1852 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001853 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001854 goto err;
1855 }
1856 }
1857 else if (cond_start && **cond_start) {
1858 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1859 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001860 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001861 goto err;
1862 }
1863
Willy Tarreau63af98d2014-05-18 08:11:41 +02001864 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001865 (dir == SMP_OPT_DIR_REQ) ?
1866 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1867 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1868 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001869
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001870 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001871 if (!preg) {
1872 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001873 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001874 goto err;
1875 }
1876
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001877 cs = !(flags & REG_ICASE);
1878 cap = !(flags & REG_NOSUB);
1879 error = NULL;
1880 if (!regex_comp(reg, preg, cs, cap, &error)) {
1881 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1882 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001883 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001884 goto err;
1885 }
1886
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001887 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001888 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889 if (repl && err) {
1890 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1891 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001892 ret_code |= ERR_ALERT | ERR_FATAL;
1893 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001894 }
1895
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001896 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001897 ret_code |= ERR_WARN;
1898
1899 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001900
Willy Tarreau63af98d2014-05-18 08:11:41 +02001901 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001902 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001903 err:
1904 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001905 free(errmsg);
1906 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001907}
1908
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909/*
William Lallemand51097192015-04-14 16:35:22 +02001910 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001911 * Returns the error code, 0 if OK, or any combination of :
1912 * - ERR_ABORT: must abort ASAP
1913 * - ERR_FATAL: we can continue parsing but not start the service
1914 * - ERR_WARN: a warning has been emitted
1915 * - ERR_ALERT: an alert has been emitted
1916 * Only the two first ones can stop processing, the two others are just
1917 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001919int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1920{
1921 static struct peers *curpeers = NULL;
1922 struct peer *newpeer = NULL;
1923 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001924 struct bind_conf *bind_conf;
1925 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001926 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001927 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001928
1929 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001930 if (!*args[1]) {
1931 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001932 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001933 goto out;
1934 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001935
William Lallemand6e62fb62015-04-28 16:55:23 +02001936 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1937 goto out;
1938
Emeric Brun32da3c42010-09-23 18:39:19 +02001939 err = invalid_char(args[1]);
1940 if (err) {
1941 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1942 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001943 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001944 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001945 }
1946
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001947 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001948 /*
1949 * If there are two proxies with the same name only following
1950 * combinations are allowed:
1951 */
1952 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001953 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 +02001954 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001955 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001956 }
1957 }
1958
Vincent Bernat02779b62016-04-03 13:48:43 +02001959 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001960 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1961 err_code |= ERR_ALERT | ERR_ABORT;
1962 goto out;
1963 }
1964
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001965 curpeers->next = cfg_peers;
1966 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001967 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001968 curpeers->conf.line = linenum;
1969 curpeers->last_change = now.tv_sec;
1970 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001971 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001972 }
1973 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001974 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001975 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001976 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001977
1978 if (!*args[2]) {
1979 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1980 file, linenum, args[0]);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983 }
1984
1985 err = invalid_char(args[1]);
1986 if (err) {
1987 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1988 file, linenum, *err, args[1]);
1989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
1991 }
1992
Vincent Bernat02779b62016-04-03 13:48:43 +02001993 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001994 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1995 err_code |= ERR_ALERT | ERR_ABORT;
1996 goto out;
1997 }
1998
1999 /* the peers are linked backwards first */
2000 curpeers->count++;
2001 newpeer->next = curpeers->remote;
2002 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002003 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002004 newpeer->conf.line = linenum;
2005
2006 newpeer->last_change = now.tv_sec;
2007 newpeer->id = strdup(args[1]);
2008
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002009 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002010 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002011 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002014 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002015
2016 proto = protocol_by_family(sk->ss_family);
2017 if (!proto || !proto->connect) {
2018 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2019 file, linenum, args[0], args[1]);
2020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
2022 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002023
2024 if (port1 != port2) {
2025 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2026 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
2029 }
2030
Willy Tarreau2aa38802013-02-20 19:20:59 +01002031 if (!port1) {
2032 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2033 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
2036 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002037
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002039 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002040 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002041 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002042
Emeric Brun32da3c42010-09-23 18:39:19 +02002043 if (strcmp(newpeer->id, localpeer) == 0) {
2044 /* Current is local peer, it define a frontend */
2045 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002046 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002047
2048 if (!curpeers->peers_fe) {
2049 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2051 err_code |= ERR_ALERT | ERR_ABORT;
2052 goto out;
2053 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002054
Willy Tarreau237250c2011-07-29 01:49:03 +02002055 init_new_proxy(curpeers->peers_fe);
2056 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002057 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002058 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2059 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002060 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002061
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002062 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002063
Willy Tarreau902636f2013-03-10 19:44:48 +01002064 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2065 if (errmsg && *errmsg) {
2066 indent_msg(&errmsg, 2);
2067 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002068 }
2069 else
2070 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2071 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002072 err_code |= ERR_FATAL;
2073 goto out;
2074 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002075
2076 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002077 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002078 l->maxconn = curpeers->peers_fe->maxconn;
2079 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002080 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002081 l->analysers |= curpeers->peers_fe->fe_req_ana;
2082 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002083 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2084 global.maxsock += l->maxconn;
2085 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002086 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002087 else {
2088 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2089 file, linenum, args[0], args[1],
2090 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2091 err_code |= ERR_FATAL;
2092 goto out;
2093 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002094 }
2095 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002096 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2097 curpeers->state = PR_STSTOPPED;
2098 }
2099 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2100 curpeers->state = PR_STNEW;
2101 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002102 else if (*args[0] != 0) {
2103 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
2106 }
2107
2108out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002109 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 return err_code;
2111}
2112
Baptiste Assmann325137d2015-04-13 23:40:55 +02002113/*
2114 * Parse a <resolvers> section.
2115 * Returns the error code, 0 if OK, or any combination of :
2116 * - ERR_ABORT: must abort ASAP
2117 * - ERR_FATAL: we can continue parsing but not start the service
2118 * - ERR_WARN: a warning has been emitted
2119 * - ERR_ALERT: an alert has been emitted
2120 * Only the two first ones can stop processing, the two others are just
2121 * indicators.
2122 */
2123int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2124{
2125 static struct dns_resolvers *curr_resolvers = NULL;
2126 struct dns_nameserver *newnameserver = NULL;
2127 const char *err;
2128 int err_code = 0;
2129 char *errmsg = NULL;
2130
2131 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2132 if (!*args[1]) {
2133 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2134 err_code |= ERR_ALERT | ERR_ABORT;
2135 goto out;
2136 }
2137
2138 err = invalid_char(args[1]);
2139 if (err) {
2140 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2141 file, linenum, *err, args[0], args[1]);
2142 err_code |= ERR_ALERT | ERR_ABORT;
2143 goto out;
2144 }
2145
2146 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2147 /* Error if two resolvers owns the same name */
2148 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2149 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2150 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2151 err_code |= ERR_ALERT | ERR_ABORT;
2152 }
2153 }
2154
Vincent Bernat02779b62016-04-03 13:48:43 +02002155 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002156 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2157 err_code |= ERR_ALERT | ERR_ABORT;
2158 goto out;
2159 }
2160
2161 /* default values */
2162 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2163 curr_resolvers->conf.file = strdup(file);
2164 curr_resolvers->conf.line = linenum;
2165 curr_resolvers->id = strdup(args[1]);
2166 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002167 /* default maximum response size */
2168 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002169 /* default hold period for nx, other, refuse and timeout is 30s */
2170 curr_resolvers->hold.nx = 30000;
2171 curr_resolvers->hold.other = 30000;
2172 curr_resolvers->hold.refused = 30000;
2173 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002174 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002175 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002176 curr_resolvers->hold.valid = 10000;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002177 curr_resolvers->timeout.resolve = 1000;
2178 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002179 curr_resolvers->resolve_retries = 3;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002180 curr_resolvers->nb_nameservers = 0;
2181 LIST_INIT(&curr_resolvers->nameservers);
2182 LIST_INIT(&curr_resolvers->resolutions.curr);
2183 LIST_INIT(&curr_resolvers->resolutions.wait);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002184 }
2185 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2186 struct sockaddr_storage *sk;
2187 int port1, port2;
2188 struct protocol *proto;
2189
2190 if (!*args[2]) {
2191 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2192 file, linenum, args[0]);
2193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
2195 }
2196
2197 err = invalid_char(args[1]);
2198 if (err) {
2199 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2200 file, linenum, *err, args[1]);
2201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
2203 }
2204
Christopher Faulet67957bd2017-09-27 11:00:59 +02002205 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002206 /* Error if two resolvers owns the same name */
2207 if (strcmp(newnameserver->id, args[1]) == 0) {
2208 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2209 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2210 err_code |= ERR_ALERT | ERR_FATAL;
2211 }
2212 }
2213
Vincent Bernat02779b62016-04-03 13:48:43 +02002214 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002215 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2216 err_code |= ERR_ALERT | ERR_ABORT;
2217 goto out;
2218 }
2219
2220 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002221 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002222 newnameserver->resolvers = curr_resolvers;
2223 newnameserver->conf.file = strdup(file);
2224 newnameserver->conf.line = linenum;
2225 newnameserver->id = strdup(args[1]);
2226
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002227 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002228 if (!sk) {
2229 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233
2234 proto = protocol_by_family(sk->ss_family);
2235 if (!proto || !proto->connect) {
2236 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2237 file, linenum, args[0], args[1]);
2238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
2240 }
2241
2242 if (port1 != port2) {
2243 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2244 file, linenum, args[0], args[1], args[2]);
2245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
2247 }
2248
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002249 if (!port1 && !port2) {
2250 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2251 file, linenum, args[0], args[1]);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
2254 }
2255
Baptiste Assmann325137d2015-04-13 23:40:55 +02002256 newnameserver->addr = *sk;
2257 }
2258 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2259 const char *res;
2260 unsigned int time;
2261
2262 if (!*args[2]) {
2263 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2264 file, linenum, args[0]);
2265 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
2268 }
2269 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2270 if (res) {
2271 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2272 file, linenum, *res, args[0]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002276 if (strcmp(args[1], "nx") == 0)
2277 curr_resolvers->hold.nx = time;
2278 else if (strcmp(args[1], "other") == 0)
2279 curr_resolvers->hold.other = time;
2280 else if (strcmp(args[1], "refused") == 0)
2281 curr_resolvers->hold.refused = time;
2282 else if (strcmp(args[1], "timeout") == 0)
2283 curr_resolvers->hold.timeout = time;
2284 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002285 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002286 else if (strcmp(args[1], "obsolete") == 0)
2287 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002288 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002289 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002290 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
2295 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002296 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002297 int i = 0;
2298
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002299 if (!*args[1]) {
2300 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2301 file, linenum, args[0]);
2302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
2304 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002305
2306 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002307 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2308 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2309 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
2312 }
2313
2314 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002315 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002316 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002317 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2318 file, linenum, args[0]);
2319 err_code |= ERR_WARN;
2320 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002321 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002322 else if (strcmp(args[0], "resolve_retries") == 0) {
2323 if (!*args[1]) {
2324 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2325 file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329 curr_resolvers->resolve_retries = atoi(args[1]);
2330 }
2331 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002332 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002333 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002334 file, linenum, args[0]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002338 else if (strcmp(args[1], "retry") == 0 ||
2339 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002340 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002341 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002342
2343 if (!*args[2]) {
2344 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2345 file, linenum, args[0], args[1]);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002349 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002350 if (res) {
2351 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2352 file, linenum, *res, args[0], args[1]);
2353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
2355 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002356 if (args[1][2] == 't')
2357 curr_resolvers->timeout.retry = tout;
2358 else
2359 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002360 }
2361 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002362 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +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 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002367 } /* neither "nameserver" nor "resolvers" */
2368 else if (*args[0] != 0) {
2369 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
2372 }
2373
2374 out:
2375 free(errmsg);
2376 return err_code;
2377}
Simon Horman0d16a402015-01-30 11:22:58 +09002378
2379/*
William Lallemand51097192015-04-14 16:35:22 +02002380 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002381 * Returns the error code, 0 if OK, or any combination of :
2382 * - ERR_ABORT: must abort ASAP
2383 * - ERR_FATAL: we can continue parsing but not start the service
2384 * - ERR_WARN: a warning has been emitted
2385 * - ERR_ALERT: an alert has been emitted
2386 * Only the two first ones can stop processing, the two others are just
2387 * indicators.
2388 */
2389int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2390{
2391 static struct mailers *curmailers = NULL;
2392 struct mailer *newmailer = NULL;
2393 const char *err;
2394 int err_code = 0;
2395 char *errmsg = NULL;
2396
2397 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2398 if (!*args[1]) {
2399 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 err = invalid_char(args[1]);
2405 if (err) {
2406 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2407 file, linenum, *err, args[0], args[1]);
2408 err_code |= ERR_ALERT | ERR_ABORT;
2409 goto out;
2410 }
2411
2412 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2413 /*
2414 * If there are two proxies with the same name only following
2415 * combinations are allowed:
2416 */
2417 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002418 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 +09002419 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002421 }
2422 }
2423
Vincent Bernat02779b62016-04-03 13:48:43 +02002424 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002425 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2426 err_code |= ERR_ALERT | ERR_ABORT;
2427 goto out;
2428 }
2429
2430 curmailers->next = mailers;
2431 mailers = curmailers;
2432 curmailers->conf.file = strdup(file);
2433 curmailers->conf.line = linenum;
2434 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002435 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2436 * But need enough time so that timeouts don't occur
2437 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002438 }
2439 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2440 struct sockaddr_storage *sk;
2441 int port1, port2;
2442 struct protocol *proto;
2443
2444 if (!*args[2]) {
2445 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
2451 err = invalid_char(args[1]);
2452 if (err) {
2453 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2454 file, linenum, *err, args[1]);
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
2458
Vincent Bernat02779b62016-04-03 13:48:43 +02002459 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002460 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2461 err_code |= ERR_ALERT | ERR_ABORT;
2462 goto out;
2463 }
2464
2465 /* the mailers are linked backwards first */
2466 curmailers->count++;
2467 newmailer->next = curmailers->mailer_list;
2468 curmailers->mailer_list = newmailer;
2469 newmailer->mailers = curmailers;
2470 newmailer->conf.file = strdup(file);
2471 newmailer->conf.line = linenum;
2472
2473 newmailer->id = strdup(args[1]);
2474
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002475 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002476 if (!sk) {
2477 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481
2482 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002483 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2484 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002485 file, linenum, args[0], args[1]);
2486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
2488 }
2489
2490 if (port1 != port2) {
2491 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2492 file, linenum, args[0], args[1], args[2]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
2497 if (!port1) {
2498 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2499 file, linenum, args[0], args[1], args[2]);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
2504 newmailer->addr = *sk;
2505 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002506 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002507 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002508 }
2509 else if (strcmp(args[0], "timeout") == 0) {
2510 if (!*args[1]) {
2511 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2512 file, linenum, args[0]);
2513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
2515 }
2516 else if (strcmp(args[1], "mail") == 0) {
2517 const char *res;
2518 unsigned int timeout_mail;
2519 if (!*args[2]) {
2520 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2521 file, linenum, args[0], args[1]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2526 if (res) {
2527 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2528 file, linenum, *res, args[0]);
2529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
2531 }
2532 if (timeout_mail <= 0) {
2533 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
2536 }
2537 curmailers->timeout.mail = timeout_mail;
2538 } else {
2539 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2540 file, linenum, args[0], args[1]);
2541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
2543 }
2544 }
Simon Horman0d16a402015-01-30 11:22:58 +09002545 else if (*args[0] != 0) {
2546 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
2549 }
2550
2551out:
2552 free(errmsg);
2553 return err_code;
2554}
2555
Simon Horman9dc49962015-01-30 11:22:59 +09002556static void free_email_alert(struct proxy *p)
2557{
2558 free(p->email_alert.mailers.name);
2559 p->email_alert.mailers.name = NULL;
2560 free(p->email_alert.from);
2561 p->email_alert.from = NULL;
2562 free(p->email_alert.to);
2563 p->email_alert.to = NULL;
2564 free(p->email_alert.myhostname);
2565 p->email_alert.myhostname = NULL;
2566}
2567
Willy Tarreau3842f002009-06-14 11:39:52 +02002568int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569{
2570 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002571 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002572 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002573 int rc;
2574 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002575 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002576 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002577 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002578 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002579 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581 if (!strcmp(args[0], "listen"))
2582 rc = PR_CAP_LISTEN;
2583 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002584 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002585 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002586 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002587 else
2588 rc = PR_CAP_NONE;
2589
2590 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 if (!*args[1]) {
2592 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002593 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_ABORT;
2596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002598
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002599 err = invalid_char(args[1]);
2600 if (err) {
2601 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2602 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002604 }
2605
Willy Tarreau8f50b682015-05-26 11:45:02 +02002606 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2607 if (curproxy) {
2608 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2609 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2610 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002612 }
2613
Vincent Bernat02779b62016-04-03 13:48:43 +02002614 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_ALERT | ERR_ABORT;
2617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002619
Willy Tarreau97cb7802010-01-03 20:23:58 +01002620 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 curproxy->next = proxy;
2622 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002623 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2624 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002625 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002627 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002628 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629
William Lallemand6e62fb62015-04-28 16:55:23 +02002630 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2631 if (curproxy->cap & PR_CAP_FE)
2632 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 }
2635
2636 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002637 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002638 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002639
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002642 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002643 curproxy->no_options = defproxy.no_options;
2644 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002645 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002646 curproxy->except_net = defproxy.except_net;
2647 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002648 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002649 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002651 if (defproxy.fwdfor_hdr_len) {
2652 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2653 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2654 }
2655
Willy Tarreaub86db342009-11-30 11:50:16 +01002656 if (defproxy.orgto_hdr_len) {
2657 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2658 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2659 }
2660
Mark Lamourinec2247f02012-01-04 13:02:01 -05002661 if (defproxy.server_id_hdr_len) {
2662 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2663 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2664 }
2665
Willy Tarreau977b8e42006-12-29 14:19:17 +01002666 if (curproxy->cap & PR_CAP_FE) {
2667 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002668 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002669 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002670
2671 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002672 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2673 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002674
2675 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002679 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002680 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002681 curproxy->fullconn = defproxy.fullconn;
2682 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002683 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002684 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002686 if (defproxy.check_req) {
2687 curproxy->check_req = calloc(1, defproxy.check_len);
2688 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2689 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002690 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002692 if (defproxy.expect_str) {
2693 curproxy->expect_str = strdup(defproxy.expect_str);
2694 if (defproxy.expect_regex) {
2695 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002696 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2697 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002698 }
2699 }
2700
Willy Tarreau67402132012-05-31 20:40:20 +02002701 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702 if (defproxy.cookie_name)
2703 curproxy->cookie_name = strdup(defproxy.cookie_name);
2704 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002705
2706 if (defproxy.dyncookie_key)
2707 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002708 if (defproxy.cookie_domain)
2709 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002710
Willy Tarreau31936852010-10-06 16:59:56 +02002711 if (defproxy.cookie_maxidle)
2712 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2713
2714 if (defproxy.cookie_maxlife)
2715 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2716
Emeric Brun647caf12009-06-30 17:57:00 +02002717 if (defproxy.rdp_cookie_name)
2718 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2719 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2720
Willy Tarreau01732802007-11-01 22:48:15 +01002721 if (defproxy.url_param_name)
2722 curproxy->url_param_name = strdup(defproxy.url_param_name);
2723 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002724
Benoitaffb4812009-03-25 13:02:10 +01002725 if (defproxy.hh_name)
2726 curproxy->hh_name = strdup(defproxy.hh_name);
2727 curproxy->hh_len = defproxy.hh_len;
2728 curproxy->hh_match_domain = defproxy.hh_match_domain;
2729
Willy Tarreauef9a3602012-12-08 22:29:20 +01002730 if (defproxy.conn_src.iface_name)
2731 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2732 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002733 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002734#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002735 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002736#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002737 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002740 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741 if (defproxy.capture_name)
2742 curproxy->capture_name = strdup(defproxy.capture_name);
2743 curproxy->capture_namelen = defproxy.capture_namelen;
2744 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746
Willy Tarreau977b8e42006-12-29 14:19:17 +01002747 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002748 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002749 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002750 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002751 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002752 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002753 curproxy->mon_net = defproxy.mon_net;
2754 curproxy->mon_mask = defproxy.mon_mask;
2755 if (defproxy.monitor_uri)
2756 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2757 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002758 if (defproxy.defbe.name)
2759 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002760
2761 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002762 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2763 if (curproxy->conf.logformat_string &&
2764 curproxy->conf.logformat_string != default_http_log_format &&
2765 curproxy->conf.logformat_string != default_tcp_log_format &&
2766 curproxy->conf.logformat_string != clf_http_log_format)
2767 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2768
2769 if (defproxy.conf.lfs_file) {
2770 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2771 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2772 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002773
2774 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2775 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2776 if (curproxy->conf.logformat_sd_string &&
2777 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2778 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2779
2780 if (defproxy.conf.lfsd_file) {
2781 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2782 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2783 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002784 }
2785
2786 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002787 curproxy->timeout.connect = defproxy.timeout.connect;
2788 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002789 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002790 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002791 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002792 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002793 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002794 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002795 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002796 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002797 }
2798
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002800 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002801
2802 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002803 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002804 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002805 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002806 LIST_INIT(&node->list);
2807 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2808 }
2809
Willy Tarreau62a61232013-04-12 18:13:46 +02002810 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2811 if (curproxy->conf.uniqueid_format_string)
2812 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2813
Dragan Dosen43885c72015-10-01 13:18:13 +02002814 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002815
Willy Tarreau62a61232013-04-12 18:13:46 +02002816 if (defproxy.conf.uif_file) {
2817 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2818 curproxy->conf.uif_line = defproxy.conf.uif_line;
2819 }
William Lallemanda73203e2012-03-12 12:48:57 +01002820
2821 /* copy default header unique id */
2822 if (defproxy.header_unique_id)
2823 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2824
William Lallemand82fe75c2012-10-23 10:25:10 +02002825 /* default compression options */
2826 if (defproxy.comp != NULL) {
2827 curproxy->comp = calloc(1, sizeof(struct comp));
2828 curproxy->comp->algos = defproxy.comp->algos;
2829 curproxy->comp->types = defproxy.comp->types;
2830 }
2831
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002833 curproxy->conf.used_listener_id = EB_ROOT;
2834 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002835
Simon Horman98637e52014-06-20 12:30:16 +09002836 if (defproxy.check_path)
2837 curproxy->check_path = strdup(defproxy.check_path);
2838 if (defproxy.check_command)
2839 curproxy->check_command = strdup(defproxy.check_command);
2840
Simon Horman9dc49962015-01-30 11:22:59 +09002841 if (defproxy.email_alert.mailers.name)
2842 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2843 if (defproxy.email_alert.from)
2844 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2845 if (defproxy.email_alert.to)
2846 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2847 if (defproxy.email_alert.myhostname)
2848 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002849 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002850 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002851
Willy Tarreau93893792009-07-23 13:19:11 +02002852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 }
2854 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2855 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002856 /* FIXME-20070101: we should do this too at the end of the
2857 * config parsing to free all default values.
2858 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002859 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2860 err_code |= ERR_ABORT;
2861 goto out;
2862 }
2863
Willy Tarreaua534fea2008-08-03 12:19:50 +02002864 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002865 free(defproxy.check_command);
2866 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002867 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002868 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002869 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002870 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002871 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002872 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002873 free(defproxy.capture_name);
2874 free(defproxy.monitor_uri);
2875 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002876 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002877 free(defproxy.fwdfor_hdr_name);
2878 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002879 free(defproxy.orgto_hdr_name);
2880 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002881 free(defproxy.server_id_hdr_name);
2882 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002883 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002884 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002885 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002886 free(defproxy.expect_regex);
2887 defproxy.expect_regex = NULL;
2888 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002889
Willy Tarreau62a61232013-04-12 18:13:46 +02002890 if (defproxy.conf.logformat_string != default_http_log_format &&
2891 defproxy.conf.logformat_string != default_tcp_log_format &&
2892 defproxy.conf.logformat_string != clf_http_log_format)
2893 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002894
Willy Tarreau62a61232013-04-12 18:13:46 +02002895 free(defproxy.conf.uniqueid_format_string);
2896 free(defproxy.conf.lfs_file);
2897 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002898 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002899 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002900
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002901 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2902 free(defproxy.conf.logformat_sd_string);
2903 free(defproxy.conf.lfsd_file);
2904
Willy Tarreaua534fea2008-08-03 12:19:50 +02002905 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002906 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002907
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 /* we cannot free uri_auth because it might already be used */
2909 init_default_instance();
2910 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002911 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2912 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002913 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
2916 else if (curproxy == NULL) {
2917 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002921
2922 /* update the current file and line being parsed */
2923 curproxy->conf.args.file = curproxy->conf.file;
2924 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925
2926 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002927 if (!strcmp(args[0], "server") ||
2928 !strcmp(args[0], "default-server") ||
2929 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002930 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2931 if (err_code & ERR_FATAL)
2932 goto out;
2933 }
2934 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002935 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002936 int cur_arg;
2937
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 if (curproxy == &defproxy) {
2939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002943 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945
Willy Tarreau24709282013-03-10 21:32:12 +01002946 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002947 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002952
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002953 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002954
2955 /* use default settings for unix sockets */
2956 bind_conf->ux.uid = global.unix_bind.ux.uid;
2957 bind_conf->ux.gid = global.unix_bind.ux.gid;
2958 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002959
2960 /* NOTE: the following line might create several listeners if there
2961 * are comma-separated IPs or port ranges. So all further processing
2962 * will have to be applied to all listeners created after last_listen.
2963 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002964 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2965 if (errmsg && *errmsg) {
2966 indent_msg(&errmsg, 2);
2967 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002968 }
2969 else
2970 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2971 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002975
Willy Tarreau4348fad2012-09-20 16:48:07 +02002976 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2977 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002978 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002979 }
2980
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002981 cur_arg = 2;
2982 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002983 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002984 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002985 char *err;
2986
Willy Tarreau26982662012-09-12 23:17:10 +02002987 kw = bind_find_kw(args[cur_arg]);
2988 if (kw) {
2989 char *err = NULL;
2990 int code;
2991
2992 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002993 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2994 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002995 cur_arg += 1 + kw->skip ;
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999
Willy Tarreau4348fad2012-09-20 16:48:07 +02003000 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003001 err_code |= code;
3002
3003 if (code) {
3004 if (err && *err) {
3005 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003006 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003007 }
3008 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003009 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3010 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003011 if (code & ERR_FATAL) {
3012 free(err);
3013 cur_arg += 1 + kw->skip;
3014 goto out;
3015 }
3016 }
3017 free(err);
3018 cur_arg += 1 + kw->skip;
3019 continue;
3020 }
3021
Willy Tarreau8638f482012-09-18 18:01:17 +02003022 err = NULL;
3023 if (!bind_dumped) {
3024 bind_dump_kws(&err);
3025 indent_msg(&err, 4);
3026 bind_dumped = 1;
3027 }
3028
3029 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3030 file, linenum, args[0], args[1], args[cur_arg],
3031 err ? " Registered keywords :" : "", err ? err : "");
3032 free(err);
3033
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003036 }
Willy Tarreau93893792009-07-23 13:19:11 +02003037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 }
3039 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003040 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3042 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003046 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003048
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 /* flush useless bits */
3050 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003053 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003054 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003056
William Lallemanddf1425a2015-04-28 20:17:49 +02003057 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3058 goto out;
3059
Willy Tarreau1c47f852006-07-09 08:22:27 +02003060 if (!*args[1]) {
3061 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003065 }
3066
Willy Tarreaua534fea2008-08-03 12:19:50 +02003067 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003068 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003069 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003070 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003071 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3072
Willy Tarreau93893792009-07-23 13:19:11 +02003073 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003076 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3077 goto out;
3078
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3080 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3081 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3082 else {
3083 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
3087 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003088 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003089 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003090
3091 if (curproxy == &defproxy) {
3092 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003096 }
3097
William Lallemanddf1425a2015-04-28 20:17:49 +02003098 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3099 goto out;
3100
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003101 if (!*args[1]) {
3102 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003106 }
3107
3108 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003109 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003110 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003111
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003112 if (curproxy->uuid <= 0) {
3113 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003114 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003117 }
3118
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003119 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3120 if (node) {
3121 struct proxy *target = container_of(node, struct proxy, conf.id);
3122 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3123 file, linenum, proxy_type_str(curproxy), curproxy->id,
3124 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003129 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003130 else if (!strcmp(args[0], "description")) {
3131 int i, len=0;
3132 char *d;
3133
Cyril Bonté99ed3272010-01-24 23:29:44 +01003134 if (curproxy == &defproxy) {
3135 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3136 file, linenum, args[0]);
3137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
3139 }
3140
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003141 if (!*args[1]) {
3142 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3143 file, linenum, args[0]);
3144 return -1;
3145 }
3146
Willy Tarreau348acfe2014-04-14 15:00:39 +02003147 for (i = 1; *args[i]; i++)
3148 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003149
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003150 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003151 curproxy->desc = d;
3152
Willy Tarreau348acfe2014-04-14 15:00:39 +02003153 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3154 for (i = 2; *args[i]; i++)
3155 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003156
3157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003159 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 curproxy->state = PR_STSTOPPED;
3162 }
3163 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003164 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 curproxy->state = PR_STNEW;
3167 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003168 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3169 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003170 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003171
3172 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003173 unsigned int low, high;
3174
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003175 if (strcmp(args[cur_arg], "all") == 0) {
3176 set = 0;
3177 break;
3178 }
3179 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003180 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003181 }
3182 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003183 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003184 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003185 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003186 char *dash = strchr(args[cur_arg], '-');
3187
3188 low = high = str2uic(args[cur_arg]);
3189 if (dash)
3190 high = str2uic(dash + 1);
3191
3192 if (high < low) {
3193 unsigned int swap = low;
3194 low = high;
3195 high = swap;
3196 }
3197
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003198 if (low < 1 || high > LONGBITS) {
3199 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3200 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003203 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003204 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003205 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003206 }
3207 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003208 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3209 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003212 }
3213 cur_arg++;
3214 }
3215 curproxy->bind_proc = set;
3216 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003217 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003218 if (curproxy == &defproxy) {
3219 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003222 }
3223
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003224 err = invalid_char(args[1]);
3225 if (err) {
3226 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3227 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003229 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003230 }
3231
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003232 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003233 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3234 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003237 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003238 }
3239 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3240
3241 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3242 err_code |= ERR_WARN;
3243
3244 if (*(args[1]) == 0) {
3245 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3246 file, linenum, args[0]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250 free(curproxy->dyncookie_key);
3251 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3254 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255
Willy Tarreau977b8e42006-12-29 14:19:17 +01003256 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003258
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 if (*(args[1]) == 0) {
3260 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3261 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003265
Willy Tarreau67402132012-05-31 20:40:20 +02003266 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003267 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003268 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003269 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 curproxy->cookie_name = strdup(args[1]);
3271 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003272
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 cur_arg = 2;
3274 while (*(args[cur_arg])) {
3275 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003276 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
3278 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003279 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 }
3281 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003282 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
3284 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003285 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
3287 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003288 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003290 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003291 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003294 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003296 else if (!strcmp(args[cur_arg], "httponly")) {
3297 curproxy->ck_opts |= PR_CK_HTTPONLY;
3298 }
3299 else if (!strcmp(args[cur_arg], "secure")) {
3300 curproxy->ck_opts |= PR_CK_SECURE;
3301 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003302 else if (!strcmp(args[cur_arg], "domain")) {
3303 if (!*args[cur_arg + 1]) {
3304 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3305 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003308 }
3309
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003310 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003311 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003312 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3313 " dots nor does not start with a dot."
3314 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003315 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003316 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003317 }
3318
3319 err = invalid_domainchar(args[cur_arg + 1]);
3320 if (err) {
3321 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3322 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003325 }
3326
Willy Tarreau68a897b2009-12-03 23:28:34 +01003327 if (!curproxy->cookie_domain) {
3328 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3329 } else {
3330 /* one domain was already specified, add another one by
3331 * building the string which will be returned along with
3332 * the cookie.
3333 */
3334 char *new_ptr;
3335 int new_len = strlen(curproxy->cookie_domain) +
3336 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3337 new_ptr = malloc(new_len);
3338 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3339 free(curproxy->cookie_domain);
3340 curproxy->cookie_domain = new_ptr;
3341 }
Willy Tarreau31936852010-10-06 16:59:56 +02003342 cur_arg++;
3343 }
3344 else if (!strcmp(args[cur_arg], "maxidle")) {
3345 unsigned int maxidle;
3346 const char *res;
3347
3348 if (!*args[cur_arg + 1]) {
3349 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3350 file, linenum, args[cur_arg]);
3351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
3353 }
3354
3355 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3356 if (res) {
3357 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3358 file, linenum, *res, args[cur_arg]);
3359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
3361 }
3362 curproxy->cookie_maxidle = maxidle;
3363 cur_arg++;
3364 }
3365 else if (!strcmp(args[cur_arg], "maxlife")) {
3366 unsigned int maxlife;
3367 const char *res;
3368
3369 if (!*args[cur_arg + 1]) {
3370 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3371 file, linenum, args[cur_arg]);
3372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
3374 }
3375
3376 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3377 if (res) {
3378 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3379 file, linenum, *res, args[cur_arg]);
3380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003384 cur_arg++;
3385 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003386 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003387
3388 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3389 err_code |= ERR_WARN;
3390 curproxy->ck_opts |= PR_CK_DYNAMIC;
3391 }
3392
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003394 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 +02003395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 }
3399 cur_arg++;
3400 }
Willy Tarreau67402132012-05-31 20:40:20 +02003401 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3403 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003404 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406
Willy Tarreau67402132012-05-31 20:40:20 +02003407 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3409 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003410 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003412
Willy Tarreau67402132012-05-31 20:40:20 +02003413 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003414 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3415 file, linenum);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003419 else if (!strcmp(args[0], "email-alert")) {
3420 if (*(args[1]) == 0) {
3421 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3422 file, linenum, args[0]);
3423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
3425 }
3426
3427 if (!strcmp(args[1], "from")) {
3428 if (*(args[1]) == 0) {
3429 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3430 file, linenum, args[1]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
3433 }
3434 free(curproxy->email_alert.from);
3435 curproxy->email_alert.from = strdup(args[2]);
3436 }
3437 else if (!strcmp(args[1], "mailers")) {
3438 if (*(args[1]) == 0) {
3439 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3440 file, linenum, args[1]);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444 free(curproxy->email_alert.mailers.name);
3445 curproxy->email_alert.mailers.name = strdup(args[2]);
3446 }
3447 else if (!strcmp(args[1], "myhostname")) {
3448 if (*(args[1]) == 0) {
3449 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3450 file, linenum, args[1]);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454 free(curproxy->email_alert.myhostname);
3455 curproxy->email_alert.myhostname = strdup(args[2]);
3456 }
Simon Horman64e34162015-02-06 11:11:57 +09003457 else if (!strcmp(args[1], "level")) {
3458 curproxy->email_alert.level = get_log_level(args[2]);
3459 if (curproxy->email_alert.level < 0) {
3460 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3461 file, linenum, args[1], args[2]);
3462 err_code |= ERR_ALERT | ERR_FATAL;
3463 goto out;
3464 }
3465 }
Simon Horman9dc49962015-01-30 11:22:59 +09003466 else if (!strcmp(args[1], "to")) {
3467 if (*(args[1]) == 0) {
3468 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3469 file, linenum, args[1]);
3470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
3472 }
3473 free(curproxy->email_alert.to);
3474 curproxy->email_alert.to = strdup(args[2]);
3475 }
3476 else {
3477 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3478 file, linenum, args[1]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
Simon Horman64e34162015-02-06 11:11:57 +09003482 /* Indicate that the email_alert is at least partially configured */
3483 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003484 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003485 else if (!strcmp(args[0], "external-check")) {
3486 if (*(args[1]) == 0) {
3487 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3488 file, linenum, args[0]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492
3493 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003494 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003495 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003496 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003497 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3498 file, linenum, args[1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502 free(curproxy->check_command);
3503 curproxy->check_command = strdup(args[2]);
3504 }
3505 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003506 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003507 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003508 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003509 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3510 file, linenum, args[1]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514 free(curproxy->check_path);
3515 curproxy->check_path = strdup(args[2]);
3516 }
3517 else {
3518 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3519 file, linenum, args[1]);
3520 err_code |= ERR_ALERT | ERR_FATAL;
3521 goto out;
3522 }
3523 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003524 else if (!strcmp(args[0], "persist")) { /* persist */
3525 if (*(args[1]) == 0) {
3526 Alert("parsing [%s:%d] : missing persist method.\n",
3527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003530 }
3531
3532 if (!strncmp(args[1], "rdp-cookie", 10)) {
3533 curproxy->options2 |= PR_O2_RDPC_PRST;
3534
Emeric Brunb982a3d2010-01-04 15:45:53 +01003535 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003536 const char *beg, *end;
3537
3538 beg = args[1] + 11;
3539 end = strchr(beg, ')');
3540
William Lallemanddf1425a2015-04-28 20:17:49 +02003541 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3542 goto out;
3543
Emeric Brun647caf12009-06-30 17:57:00 +02003544 if (!end || end == beg) {
3545 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3546 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003549 }
3550
3551 free(curproxy->rdp_cookie_name);
3552 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3553 curproxy->rdp_cookie_len = end-beg;
3554 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003555 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003556 free(curproxy->rdp_cookie_name);
3557 curproxy->rdp_cookie_name = strdup("msts");
3558 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3559 }
3560 else { /* syntax */
3561 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3562 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003565 }
3566 }
3567 else {
3568 Alert("parsing [%s:%d] : unknown persist method.\n",
3569 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003572 }
3573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003575 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
3578 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003579 else if (!strcmp(args[0], "load-server-state-from-file")) {
3580 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3581 err_code |= ERR_WARN;
3582 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3583 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3584 }
3585 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3586 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3587 }
3588 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3589 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3590 }
3591 else {
3592 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3593 file, linenum, args[0], args[1]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597 }
3598 else if (!strcmp(args[0], "server-state-file-name")) {
3599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3600 err_code |= ERR_WARN;
3601 if (*(args[1]) == 0) {
3602 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3603 file, linenum, args[0]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607 else if (!strcmp(args[1], "use-backend-name"))
3608 curproxy->server_state_file_name = strdup(curproxy->id);
3609 else
3610 curproxy->server_state_file_name = strdup(args[1]);
3611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003613 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003615
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003617 if (curproxy == &defproxy) {
3618 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
3621 }
3622
William Lallemand1a748ae2015-05-19 16:37:23 +02003623 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3624 goto out;
3625
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 if (*(args[4]) == 0) {
3627 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003632 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 curproxy->capture_name = strdup(args[2]);
3634 curproxy->capture_namelen = strlen(curproxy->capture_name);
3635 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 curproxy->to_log |= LW_COOKIE;
3637 }
3638 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3639 struct cap_hdr *hdr;
3640
3641 if (curproxy == &defproxy) {
3642 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 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 }
3646
William Lallemand1a748ae2015-05-19 16:37:23 +02003647 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3648 goto out;
3649
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3651 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3652 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 }
3656
Vincent Bernat02779b62016-04-03 13:48:43 +02003657 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 hdr->next = curproxy->req_cap;
3659 hdr->name = strdup(args[3]);
3660 hdr->namelen = strlen(args[3]);
3661 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003662 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 hdr->index = curproxy->nb_req_cap++;
3664 curproxy->req_cap = hdr;
3665 curproxy->to_log |= LW_REQHDR;
3666 }
3667 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3668 struct cap_hdr *hdr;
3669
3670 if (curproxy == &defproxy) {
3671 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 +02003672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003674 }
3675
William Lallemand1a748ae2015-05-19 16:37:23 +02003676 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3677 goto out;
3678
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3680 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3681 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003685 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 hdr->next = curproxy->rsp_cap;
3687 hdr->name = strdup(args[3]);
3688 hdr->namelen = strlen(args[3]);
3689 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003690 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 hdr->index = curproxy->nb_rsp_cap++;
3692 curproxy->rsp_cap = hdr;
3693 curproxy->to_log |= LW_RSPHDR;
3694 }
3695 else {
3696 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3697 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 }
3701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003703 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003705
William Lallemanddf1425a2015-04-28 20:17:49 +02003706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3707 goto out;
3708
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 if (*(args[1]) == 0) {
3710 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3711 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 }
3715 curproxy->conn_retries = atol(args[1]);
3716 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003717 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003718 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003719
3720 if (curproxy == &defproxy) {
3721 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
3724 }
3725
Willy Tarreau20b0de52012-12-24 15:45:22 +01003726 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003727 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003728 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3729 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3730 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3731 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003732 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 +01003733 file, linenum, args[0]);
3734 err_code |= ERR_WARN;
3735 }
3736
Willy Tarreauff011f22011-01-06 17:51:27 +01003737 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003738
Willy Tarreauff011f22011-01-06 17:51:27 +01003739 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003740 err_code |= ERR_ALERT | ERR_ABORT;
3741 goto out;
3742 }
3743
Willy Tarreau5002f572014-04-23 01:32:02 +02003744 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003745 err_code |= warnif_cond_conflicts(rule->cond,
3746 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3747 file, linenum);
3748
Willy Tarreauff011f22011-01-06 17:51:27 +01003749 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003750 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003751 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003752 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003753
3754 if (curproxy == &defproxy) {
3755 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
3758 }
3759
3760 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003761 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003762 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3763 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003764 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3765 file, linenum, args[0]);
3766 err_code |= ERR_WARN;
3767 }
3768
3769 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3770
3771 if (!rule) {
3772 err_code |= ERR_ALERT | ERR_ABORT;
3773 goto out;
3774 }
3775
3776 err_code |= warnif_cond_conflicts(rule->cond,
3777 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3778 file, linenum);
3779
3780 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3781 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003782 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3783 /* set the header name and length into the proxy structure */
3784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3785 err_code |= ERR_WARN;
3786
3787 if (!*args[1]) {
3788 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3789 file, linenum, args[0]);
3790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
3792 }
3793
3794 /* set the desired header name */
3795 free(curproxy->server_id_hdr_name);
3796 curproxy->server_id_hdr_name = strdup(args[1]);
3797 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3798 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003799 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003800 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003801
Willy Tarreaub099aca2008-10-12 17:26:37 +02003802 if (curproxy == &defproxy) {
3803 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003806 }
3807
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003808 /* emulate "block" using "http-request block". Since these rules are supposed to
3809 * be processed before all http-request rules, we put them into their own list
3810 * and will insert them at the end.
3811 */
3812 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3813 if (!rule) {
3814 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003815 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003816 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003817 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3818 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 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003822
3823 if (!already_warned(WARN_BLOCK_DEPRECATED))
3824 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]);
3825
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003826 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003827 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003828 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003829
Cyril Bonté99ed3272010-01-24 23:29:44 +01003830 if (curproxy == &defproxy) {
3831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835
Willy Tarreaube4653b2015-05-28 15:26:58 +02003836 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003837 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3838 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003841 }
3842
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003843 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003844 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003845 err_code |= warnif_cond_conflicts(rule->cond,
3846 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3847 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003848 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003849 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003850 struct switching_rule *rule;
3851
Willy Tarreaub099aca2008-10-12 17:26:37 +02003852 if (curproxy == &defproxy) {
3853 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003856 }
3857
Willy Tarreau55ea7572007-06-17 19:56:27 +02003858 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003860
3861 if (*(args[1]) == 0) {
3862 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003865 }
3866
Willy Tarreauf51658d2014-04-23 01:21:56 +02003867 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003868 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003869 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3870 file, linenum, errmsg);
3871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
3873 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003874
Willy Tarreauf51658d2014-04-23 01:21:56 +02003875 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003876 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003877 else if (*args[2]) {
3878 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3879 file, linenum, args[2]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003883
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003884 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003885 if (!rule) {
3886 Alert("Out of memory error.\n");
3887 goto out;
3888 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003889 rule->cond = cond;
3890 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003891 rule->line = linenum;
3892 rule->file = strdup(file);
3893 if (!rule->file) {
3894 Alert("Out of memory error.\n");
3895 goto out;
3896 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003897 LIST_INIT(&rule->list);
3898 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3899 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003900 else if (strcmp(args[0], "use-server") == 0) {
3901 struct server_rule *rule;
3902
3903 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
3909 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3910 err_code |= ERR_WARN;
3911
3912 if (*(args[1]) == 0) {
3913 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917
3918 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3919 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3920 file, linenum, args[0]);
3921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
3923 }
3924
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003925 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003926 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3927 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
3931
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003932 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003933
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003934 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003935 rule->cond = cond;
3936 rule->srv.name = strdup(args[1]);
3937 LIST_INIT(&rule->list);
3938 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3939 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3940 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003941 else if ((!strcmp(args[0], "force-persist")) ||
3942 (!strcmp(args[0], "ignore-persist"))) {
3943 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003944
3945 if (curproxy == &defproxy) {
3946 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950
3951 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3952 err_code |= ERR_WARN;
3953
Willy Tarreauef6494c2010-01-28 17:12:36 +01003954 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003955 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3956 file, linenum, args[0]);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
3960
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003961 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003962 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3963 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003968 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3969 * where force-persist is applied.
3970 */
3971 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003972
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003973 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003974 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003975 if (!strcmp(args[0], "force-persist")) {
3976 rule->type = PERSIST_TYPE_FORCE;
3977 } else {
3978 rule->type = PERSIST_TYPE_IGNORE;
3979 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003980 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003981 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003982 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003983 else if (!strcmp(args[0], "stick-table")) {
3984 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003985 struct proxy *other;
3986
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003987 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003988 if (other) {
3989 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3990 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
3993 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003994
Emeric Brun32da3c42010-09-23 18:39:19 +02003995 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003996 curproxy->table.type = (unsigned int)-1;
3997 while (*args[myidx]) {
3998 const char *err;
3999
4000 if (strcmp(args[myidx], "size") == 0) {
4001 myidx++;
4002 if (!*(args[myidx])) {
4003 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4004 file, linenum, args[myidx-1]);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
4008 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4009 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4010 file, linenum, *err, args[myidx-1]);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004014 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004015 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004016 else if (strcmp(args[myidx], "peers") == 0) {
4017 myidx++;
Godbach50523162013-12-11 19:48:57 +08004018 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004019 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4020 file, linenum, args[myidx-1]);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Godbach50523162013-12-11 19:48:57 +08004023 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004024 curproxy->table.peers.name = strdup(args[myidx++]);
4025 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004026 else if (strcmp(args[myidx], "expire") == 0) {
4027 myidx++;
4028 if (!*(args[myidx])) {
4029 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4030 file, linenum, args[myidx-1]);
4031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
4033 }
4034 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4035 if (err) {
4036 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4037 file, linenum, *err, args[myidx-1]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004041 if (val > INT_MAX) {
4042 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4043 file, linenum, val);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004047 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004048 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004049 }
4050 else if (strcmp(args[myidx], "nopurge") == 0) {
4051 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004052 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004053 }
4054 else if (strcmp(args[myidx], "type") == 0) {
4055 myidx++;
4056 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4057 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4058 file, linenum, args[myidx]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004062 /* myidx already points to next arg */
4063 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004064 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004065 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004066 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004067
4068 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004069 nw = args[myidx];
4070 while (*nw) {
4071 /* the "store" keyword supports a comma-separated list */
4072 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004073 sa = NULL; /* store arg */
4074 while (*nw && *nw != ',') {
4075 if (*nw == '(') {
4076 *nw = 0;
4077 sa = ++nw;
4078 while (*nw != ')') {
4079 if (!*nw) {
4080 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4081 file, linenum, args[0], cw);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085 nw++;
4086 }
4087 *nw = '\0';
4088 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004089 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004090 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004091 if (*nw)
4092 *nw++ = '\0';
4093 type = stktable_get_data_type(cw);
4094 if (type < 0) {
4095 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4096 file, linenum, args[0], cw);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
Willy Tarreauac782882010-06-20 10:41:54 +02004100
4101 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4102 switch (err) {
4103 case PE_NONE: break;
4104 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004105 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4106 file, linenum, args[0], cw);
4107 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004108 break;
4109
4110 case PE_ARG_MISSING:
4111 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4112 file, linenum, args[0], cw);
4113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
4115
4116 case PE_ARG_NOT_USED:
4117 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4118 file, linenum, args[0], cw);
4119 err_code |= ERR_ALERT | ERR_FATAL;
4120 goto out;
4121
4122 default:
4123 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4124 file, linenum, args[0], cw);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004127 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004128 }
4129 myidx++;
4130 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004131 else {
4132 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4133 file, linenum, args[myidx]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004136 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004137 }
4138
4139 if (!curproxy->table.size) {
4140 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4141 file, linenum);
4142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
4144 }
4145
4146 if (curproxy->table.type == (unsigned int)-1) {
4147 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4148 file, linenum);
4149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
4151 }
4152 }
4153 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004154 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004155 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 int myidx = 0;
4157 const char *name = NULL;
4158 int flags;
4159
4160 if (curproxy == &defproxy) {
4161 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165
4166 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4167 err_code |= ERR_WARN;
4168 goto out;
4169 }
4170
4171 myidx++;
4172 if ((strcmp(args[myidx], "store") == 0) ||
4173 (strcmp(args[myidx], "store-request") == 0)) {
4174 myidx++;
4175 flags = STK_IS_STORE;
4176 }
4177 else if (strcmp(args[myidx], "store-response") == 0) {
4178 myidx++;
4179 flags = STK_IS_STORE | STK_ON_RSP;
4180 }
4181 else if (strcmp(args[myidx], "match") == 0) {
4182 myidx++;
4183 flags = STK_IS_MATCH;
4184 }
4185 else if (strcmp(args[myidx], "on") == 0) {
4186 myidx++;
4187 flags = STK_IS_MATCH | STK_IS_STORE;
4188 }
4189 else {
4190 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
4193 }
4194
4195 if (*(args[myidx]) == 0) {
4196 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
4199 }
4200
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004201 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004202 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004203 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004204 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
4207 }
4208
4209 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004210 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4211 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4212 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004213 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004214 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004215 goto out;
4216 }
4217 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004218 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4219 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4220 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004221 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004222 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004223 goto out;
4224 }
4225 }
4226
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004227 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004228 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004229
Emeric Brunb982a3d2010-01-04 15:45:53 +01004230 if (strcmp(args[myidx], "table") == 0) {
4231 myidx++;
4232 name = args[myidx++];
4233 }
4234
Willy Tarreauef6494c2010-01-28 17:12:36 +01004235 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004236 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004237 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4238 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004239 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004240 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004241 goto out;
4242 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004243 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004244 else if (*(args[myidx])) {
4245 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4246 file, linenum, args[0], args[myidx]);
4247 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004248 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004249 goto out;
4250 }
Emeric Brun97679e72010-09-23 17:56:44 +02004251 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004252 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004253 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004254 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004255
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004256 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004257 rule->cond = cond;
4258 rule->expr = expr;
4259 rule->flags = flags;
4260 rule->table.name = name ? strdup(name) : NULL;
4261 LIST_INIT(&rule->list);
4262 if (flags & STK_ON_RSP)
4263 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4264 else
4265 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 else if (!strcmp(args[0], "stats")) {
4268 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4269 curproxy->uri_auth = NULL; /* we must detach from the default config */
4270
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004271 if (!*args[1]) {
4272 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004273 } else if (!strcmp(args[1], "admin")) {
4274 struct stats_admin_rule *rule;
4275
4276 if (curproxy == &defproxy) {
4277 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
4280 }
4281
4282 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4283 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4284 err_code |= ERR_ALERT | ERR_ABORT;
4285 goto out;
4286 }
4287
4288 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4289 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4290 file, linenum, args[0], args[1]);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004294 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004295 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4296 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
4300
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004301 err_code |= warnif_cond_conflicts(cond,
4302 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4303 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004304
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004305 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004306 rule->cond = cond;
4307 LIST_INIT(&rule->list);
4308 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 } else if (!strcmp(args[1], "uri")) {
4310 if (*(args[2]) == 0) {
4311 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4315 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004316 err_code |= ERR_ALERT | ERR_ABORT;
4317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004318 }
4319 } else if (!strcmp(args[1], "realm")) {
4320 if (*(args[2]) == 0) {
4321 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4325 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_ABORT;
4327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004329 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004330 unsigned interval;
4331
4332 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4333 if (err) {
4334 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4335 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004338 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4339 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004340 err_code |= ERR_ALERT | ERR_ABORT;
4341 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004342 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004343 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004344 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004345
4346 if (curproxy == &defproxy) {
4347 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
4350 }
4351
4352 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4353 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4354 err_code |= ERR_ALERT | ERR_ABORT;
4355 goto out;
4356 }
4357
Willy Tarreauff011f22011-01-06 17:51:27 +01004358 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004359 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004360 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4361 file, linenum, args[0]);
4362 err_code |= ERR_WARN;
4363 }
4364
Willy Tarreauff011f22011-01-06 17:51:27 +01004365 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004366
Willy Tarreauff011f22011-01-06 17:51:27 +01004367 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004368 err_code |= ERR_ALERT | ERR_ABORT;
4369 goto out;
4370 }
4371
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004372 err_code |= warnif_cond_conflicts(rule->cond,
4373 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4374 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004375 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004376
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 } else if (!strcmp(args[1], "auth")) {
4378 if (*(args[2]) == 0) {
4379 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004380 err_code |= ERR_ALERT | ERR_FATAL;
4381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004382 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4383 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004384 err_code |= ERR_ALERT | ERR_ABORT;
4385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004386 }
4387 } else if (!strcmp(args[1], "scope")) {
4388 if (*(args[2]) == 0) {
4389 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4393 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_ALERT | ERR_ABORT;
4395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 }
4397 } else if (!strcmp(args[1], "enable")) {
4398 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_ABORT;
4401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004403 } else if (!strcmp(args[1], "hide-version")) {
4404 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4405 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_ALERT | ERR_ABORT;
4407 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004408 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004409 } else if (!strcmp(args[1], "show-legends")) {
4410 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4411 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4412 err_code |= ERR_ALERT | ERR_ABORT;
4413 goto out;
4414 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004415 } else if (!strcmp(args[1], "show-node")) {
4416
4417 if (*args[2]) {
4418 int i;
4419 char c;
4420
4421 for (i=0; args[2][i]; i++) {
4422 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004423 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4424 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004425 break;
4426 }
4427
4428 if (!i || args[2][i]) {
4429 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4430 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4431 file, linenum, args[0], args[1]);
4432 err_code |= ERR_ALERT | ERR_FATAL;
4433 goto out;
4434 }
4435 }
4436
4437 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4438 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4439 err_code |= ERR_ALERT | ERR_ABORT;
4440 goto out;
4441 }
4442 } else if (!strcmp(args[1], "show-desc")) {
4443 char *desc = NULL;
4444
4445 if (*args[2]) {
4446 int i, len=0;
4447 char *d;
4448
Willy Tarreau348acfe2014-04-14 15:00:39 +02004449 for (i = 2; *args[i]; i++)
4450 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004451
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004452 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004453
Willy Tarreau348acfe2014-04-14 15:00:39 +02004454 d += snprintf(d, desc + len - d, "%s", args[2]);
4455 for (i = 3; *args[i]; i++)
4456 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004457 }
4458
4459 if (!*args[2] && !global.desc)
4460 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4461 file, linenum, args[1]);
4462 else {
4463 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4464 free(desc);
4465 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4466 err_code |= ERR_ALERT | ERR_ABORT;
4467 goto out;
4468 }
4469 free(desc);
4470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004472stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004473 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 +01004474 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 }
4478 }
4479 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004480 int optnum;
4481
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004482 if (*(args[1]) == '\0') {
4483 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4484 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004487 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004488
4489 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4490 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004491 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4492 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4493 file, linenum, cfg_opts[optnum].name);
4494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
4496 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004497 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4498 goto out;
4499
Willy Tarreau93893792009-07-23 13:19:11 +02004500 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4501 err_code |= ERR_WARN;
4502 goto out;
4503 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004504
Willy Tarreau3842f002009-06-14 11:39:52 +02004505 curproxy->no_options &= ~cfg_opts[optnum].val;
4506 curproxy->options &= ~cfg_opts[optnum].val;
4507
4508 switch (kwm) {
4509 case KWM_STD:
4510 curproxy->options |= cfg_opts[optnum].val;
4511 break;
4512 case KWM_NO:
4513 curproxy->no_options |= cfg_opts[optnum].val;
4514 break;
4515 case KWM_DEF: /* already cleared */
4516 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004517 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004518
Willy Tarreau93893792009-07-23 13:19:11 +02004519 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004520 }
4521 }
4522
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004523 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4524 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004525 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4526 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4527 file, linenum, cfg_opts2[optnum].name);
4528 err_code |= ERR_ALERT | ERR_FATAL;
4529 goto out;
4530 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004531 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4532 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004533 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4534 err_code |= ERR_WARN;
4535 goto out;
4536 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004537
Willy Tarreau3842f002009-06-14 11:39:52 +02004538 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4539 curproxy->options2 &= ~cfg_opts2[optnum].val;
4540
4541 switch (kwm) {
4542 case KWM_STD:
4543 curproxy->options2 |= cfg_opts2[optnum].val;
4544 break;
4545 case KWM_NO:
4546 curproxy->no_options2 |= cfg_opts2[optnum].val;
4547 break;
4548 case KWM_DEF: /* already cleared */
4549 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004550 }
Willy Tarreau93893792009-07-23 13:19:11 +02004551 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004552 }
4553 }
4554
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004555 /* HTTP options override each other. They can be cancelled using
4556 * "no option xxx" which only switches to default mode if the mode
4557 * was this one (useful for cancelling options set in defaults
4558 * sections).
4559 */
4560 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004561 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4562 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004563 if (kwm == KWM_STD) {
4564 curproxy->options &= ~PR_O_HTTP_MODE;
4565 curproxy->options |= PR_O_HTTP_PCL;
4566 goto out;
4567 }
4568 else if (kwm == KWM_NO) {
4569 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4570 curproxy->options &= ~PR_O_HTTP_MODE;
4571 goto out;
4572 }
4573 }
4574 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004575 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4576 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004577 if (kwm == KWM_STD) {
4578 curproxy->options &= ~PR_O_HTTP_MODE;
4579 curproxy->options |= PR_O_HTTP_FCL;
4580 goto out;
4581 }
4582 else if (kwm == KWM_NO) {
4583 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4584 curproxy->options &= ~PR_O_HTTP_MODE;
4585 goto out;
4586 }
4587 }
4588 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004589 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4590 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004591 if (kwm == KWM_STD) {
4592 curproxy->options &= ~PR_O_HTTP_MODE;
4593 curproxy->options |= PR_O_HTTP_SCL;
4594 goto out;
4595 }
4596 else if (kwm == KWM_NO) {
4597 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4598 curproxy->options &= ~PR_O_HTTP_MODE;
4599 goto out;
4600 }
4601 }
4602 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004603 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4604 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004605 if (kwm == KWM_STD) {
4606 curproxy->options &= ~PR_O_HTTP_MODE;
4607 curproxy->options |= PR_O_HTTP_KAL;
4608 goto out;
4609 }
4610 else if (kwm == KWM_NO) {
4611 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4612 curproxy->options &= ~PR_O_HTTP_MODE;
4613 goto out;
4614 }
4615 }
4616 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004617 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4618 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004619 if (kwm == KWM_STD) {
4620 curproxy->options &= ~PR_O_HTTP_MODE;
4621 curproxy->options |= PR_O_HTTP_TUN;
4622 goto out;
4623 }
4624 else if (kwm == KWM_NO) {
4625 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4626 curproxy->options &= ~PR_O_HTTP_MODE;
4627 goto out;
4628 }
4629 }
4630
Joseph Lynch726ab712015-05-11 23:25:34 -07004631 /* Redispatch can take an integer argument that control when the
4632 * resispatch occurs. All values are relative to the retries option.
4633 * This can be cancelled using "no option xxx".
4634 */
4635 if (strcmp(args[1], "redispatch") == 0) {
4636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4637 err_code |= ERR_WARN;
4638 goto out;
4639 }
4640
4641 curproxy->no_options &= ~PR_O_REDISP;
4642 curproxy->options &= ~PR_O_REDISP;
4643
4644 switch (kwm) {
4645 case KWM_STD:
4646 curproxy->options |= PR_O_REDISP;
4647 curproxy->redispatch_after = -1;
4648 if(*args[2]) {
4649 curproxy->redispatch_after = atol(args[2]);
4650 }
4651 break;
4652 case KWM_NO:
4653 curproxy->no_options |= PR_O_REDISP;
4654 curproxy->redispatch_after = 0;
4655 break;
4656 case KWM_DEF: /* already cleared */
4657 break;
4658 }
4659 goto out;
4660 }
4661
Willy Tarreau3842f002009-06-14 11:39:52 +02004662 if (kwm != KWM_STD) {
4663 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004664 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004665 err_code |= ERR_ALERT | ERR_FATAL;
4666 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004667 }
4668
Emeric Brun3a058f32009-06-30 18:26:00 +02004669 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004670 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004671 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004672 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004673 if (*(args[2]) != '\0') {
4674 if (!strcmp(args[2], "clf")) {
4675 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004676 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004677 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004678 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004681 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004682 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4683 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004684 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004685 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4686 char *oldlogformat = "log-format";
4687 char *clflogformat = "";
4688
4689 if (curproxy->conf.logformat_string == default_http_log_format)
4690 oldlogformat = "option httplog";
4691 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4692 oldlogformat = "option tcplog";
4693 else if (curproxy->conf.logformat_string == clf_http_log_format)
4694 oldlogformat = "option httplog clf";
4695 if (logformat == clf_http_log_format)
4696 clflogformat = " clf";
4697 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4698 file, linenum, clflogformat, oldlogformat);
4699 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004700 if (curproxy->conf.logformat_string != default_http_log_format &&
4701 curproxy->conf.logformat_string != default_tcp_log_format &&
4702 curproxy->conf.logformat_string != clf_http_log_format)
4703 free(curproxy->conf.logformat_string);
4704 curproxy->conf.logformat_string = logformat;
4705
4706 free(curproxy->conf.lfs_file);
4707 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4708 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004709 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004710 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004711 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4712 char *oldlogformat = "log-format";
4713
4714 if (curproxy->conf.logformat_string == default_http_log_format)
4715 oldlogformat = "option httplog";
4716 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4717 oldlogformat = "option tcplog";
4718 else if (curproxy->conf.logformat_string == clf_http_log_format)
4719 oldlogformat = "option httplog clf";
4720 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4721 file, linenum, oldlogformat);
4722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004724 if (curproxy->conf.logformat_string != default_http_log_format &&
4725 curproxy->conf.logformat_string != default_tcp_log_format &&
4726 curproxy->conf.logformat_string != clf_http_log_format)
4727 free(curproxy->conf.logformat_string);
4728 curproxy->conf.logformat_string = default_tcp_log_format;
4729
4730 free(curproxy->conf.lfs_file);
4731 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4732 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004733
4734 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4735 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004738 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004739 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004741
William Lallemanddf1425a2015-04-28 20:17:49 +02004742 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4743 goto out;
4744
Willy Tarreau13943ab2006-12-31 00:24:10 +01004745 if (curproxy->cap & PR_CAP_FE)
4746 curproxy->options |= PR_O_TCP_CLI_KA;
4747 if (curproxy->cap & PR_CAP_BE)
4748 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 }
4750 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004751 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004752 err_code |= ERR_WARN;
4753
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004755 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004756 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004757 curproxy->options2 &= ~PR_O2_CHK_ANY;
4758 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 if (!*args[2]) { /* no argument */
4760 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4761 curproxy->check_len = strlen(DEF_CHECK_REQ);
4762 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004763 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004764 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004766 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004768 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 if (*args[4])
4770 reqlen += strlen(args[4]);
4771 else
4772 reqlen += strlen("HTTP/1.0");
4773
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004774 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004776 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004778 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4779 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004780 }
4781 else if (!strcmp(args[1], "ssl-hello-chk")) {
4782 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004785
Willy Tarreaua534fea2008-08-03 12:19:50 +02004786 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004787 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004788 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004789 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004790
4791 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
Willy Tarreau23677902007-05-08 23:50:35 +02004794 else if (!strcmp(args[1], "smtpchk")) {
4795 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004796 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004797 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004798 curproxy->options2 &= ~PR_O2_CHK_ANY;
4799 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004800
4801 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4802 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4803 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4804 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4805 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4806 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004807 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004808 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4809 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4810 } else {
4811 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4812 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4813 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4814 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4815 }
4816 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004817 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4818 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004819 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004820 else if (!strcmp(args[1], "pgsql-check")) {
4821 /* use PostgreSQL request to check servers' health */
4822 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4823 err_code |= ERR_WARN;
4824
4825 free(curproxy->check_req);
4826 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004827 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004828 curproxy->options2 |= PR_O2_PGSQL_CHK;
4829
4830 if (*(args[2])) {
4831 int cur_arg = 2;
4832
4833 while (*(args[cur_arg])) {
4834 if (strcmp(args[cur_arg], "user") == 0) {
4835 char * packet;
4836 uint32_t packet_len;
4837 uint32_t pv;
4838
4839 /* suboption header - needs additional argument for it */
4840 if (*(args[cur_arg+1]) == 0) {
4841 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4842 file, linenum, args[0], args[1], args[cur_arg]);
4843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
4845 }
4846
4847 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4848 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4849 pv = htonl(0x30000); /* protocol version 3.0 */
4850
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004851 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004852
4853 memcpy(packet + 4, &pv, 4);
4854
4855 /* copy "user" */
4856 memcpy(packet + 8, "user", 4);
4857
4858 /* copy username */
4859 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4860
4861 free(curproxy->check_req);
4862 curproxy->check_req = packet;
4863 curproxy->check_len = packet_len;
4864
4865 packet_len = htonl(packet_len);
4866 memcpy(packet, &packet_len, 4);
4867 cur_arg += 2;
4868 } else {
4869 /* unknown suboption - catchall */
4870 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4871 file, linenum, args[0], args[1]);
4872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
4874 }
4875 } /* end while loop */
4876 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004877 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4878 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004879 }
4880
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004881 else if (!strcmp(args[1], "redis-check")) {
4882 /* use REDIS PING request to check servers' health */
4883 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4884 err_code |= ERR_WARN;
4885
4886 free(curproxy->check_req);
4887 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004888 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004889 curproxy->options2 |= PR_O2_REDIS_CHK;
4890
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004891 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004892 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4893 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004894
4895 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4896 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004897 }
4898
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004899 else if (!strcmp(args[1], "mysql-check")) {
4900 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4902 err_code |= ERR_WARN;
4903
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004904 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004905 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004906 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004907 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004908
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004909 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004910 * const char mysql40_client_auth_pkt[] = {
4911 * "\x0e\x00\x00" // packet length
4912 * "\x01" // packet number
4913 * "\x00\x00" // client capabilities
4914 * "\x00\x00\x01" // max packet
4915 * "haproxy\x00" // username (null terminated string)
4916 * "\x00" // filler (always 0x00)
4917 * "\x01\x00\x00" // packet length
4918 * "\x00" // packet number
4919 * "\x01" // COM_QUIT command
4920 * };
4921 */
4922
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004923 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4924 * const char mysql41_client_auth_pkt[] = {
4925 * "\x0e\x00\x00\" // packet length
4926 * "\x01" // packet number
4927 * "\x00\x00\x00\x00" // client capabilities
4928 * "\x00\x00\x00\x01" // max packet
4929 * "\x21" // character set (UTF-8)
4930 * char[23] // All zeroes
4931 * "haproxy\x00" // username (null terminated string)
4932 * "\x00" // filler (always 0x00)
4933 * "\x01\x00\x00" // packet length
4934 * "\x00" // packet number
4935 * "\x01" // COM_QUIT command
4936 * };
4937 */
4938
4939
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004940 if (*(args[2])) {
4941 int cur_arg = 2;
4942
4943 while (*(args[cur_arg])) {
4944 if (strcmp(args[cur_arg], "user") == 0) {
4945 char *mysqluser;
4946 int packetlen, reqlen, userlen;
4947
4948 /* suboption header - needs additional argument for it */
4949 if (*(args[cur_arg+1]) == 0) {
4950 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4951 file, linenum, args[0], args[1], args[cur_arg]);
4952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
4954 }
4955 mysqluser = args[cur_arg + 1];
4956 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004957
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004958 if (*(args[cur_arg+2])) {
4959 if (!strcmp(args[cur_arg+2], "post-41")) {
4960 packetlen = userlen + 7 + 27;
4961 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004962
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004963 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004964 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004965 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004966
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004967 snprintf(curproxy->check_req, 4, "%c%c%c",
4968 ((unsigned char) packetlen & 0xff),
4969 ((unsigned char) (packetlen >> 8) & 0xff),
4970 ((unsigned char) (packetlen >> 16) & 0xff));
4971
4972 curproxy->check_req[3] = 1;
4973 curproxy->check_req[5] = 130;
4974 curproxy->check_req[11] = 1;
4975 curproxy->check_req[12] = 33;
4976 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4977 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4978 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4979 cur_arg += 3;
4980 } else {
4981 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4982 err_code |= ERR_ALERT | ERR_FATAL;
4983 goto out;
4984 }
4985 } else {
4986 packetlen = userlen + 7;
4987 reqlen = packetlen + 9;
4988
4989 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004990 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004991 curproxy->check_len = reqlen;
4992
4993 snprintf(curproxy->check_req, 4, "%c%c%c",
4994 ((unsigned char) packetlen & 0xff),
4995 ((unsigned char) (packetlen >> 8) & 0xff),
4996 ((unsigned char) (packetlen >> 16) & 0xff));
4997
4998 curproxy->check_req[3] = 1;
4999 curproxy->check_req[5] = 128;
5000 curproxy->check_req[8] = 1;
5001 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5002 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5003 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5004 cur_arg += 2;
5005 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005006 } else {
5007 /* unknown suboption - catchall */
5008 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5009 file, linenum, args[0], args[1]);
5010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
5012 }
5013 } /* end while loop */
5014 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005015 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005016 else if (!strcmp(args[1], "ldap-check")) {
5017 /* use LDAP request to check servers' health */
5018 free(curproxy->check_req);
5019 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005020 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005021 curproxy->options2 |= PR_O2_LDAP_CHK;
5022
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005023 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005024 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5025 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005026 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5027 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005028 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005029 else if (!strcmp(args[1], "spop-check")) {
5030 if (curproxy == &defproxy) {
5031 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5032 file, linenum, args[0], args[1]);
5033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
5035 }
5036 if (curproxy->cap & PR_CAP_FE) {
5037 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5038 file, linenum, args[0], args[1]);
5039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
5042
5043 /* use SPOE request to check servers' health */
5044 free(curproxy->check_req);
5045 curproxy->check_req = NULL;
5046 curproxy->options2 &= ~PR_O2_CHK_ANY;
5047 curproxy->options2 |= PR_O2_SPOP_CHK;
5048
Christopher Faulet8ef75252017-02-20 22:56:03 +01005049 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005050 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053 }
5054 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5055 goto out;
5056 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005057 else if (!strcmp(args[1], "tcp-check")) {
5058 /* use raw TCPCHK send/expect to check servers' health */
5059 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5060 err_code |= ERR_WARN;
5061
5062 free(curproxy->check_req);
5063 curproxy->check_req = NULL;
5064 curproxy->options2 &= ~PR_O2_CHK_ANY;
5065 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005066 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5067 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005068 }
Simon Horman98637e52014-06-20 12:30:16 +09005069 else if (!strcmp(args[1], "external-check")) {
5070 /* excute an external command to check servers' health */
5071 free(curproxy->check_req);
5072 curproxy->check_req = NULL;
5073 curproxy->options2 &= ~PR_O2_CHK_ANY;
5074 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005075 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5076 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005077 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005078 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005079 int cur_arg;
5080
5081 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5082 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005083 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005084
Willy Tarreau87cf5142011-08-19 22:57:24 +02005085 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005086
5087 free(curproxy->fwdfor_hdr_name);
5088 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5089 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5090
5091 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5092 cur_arg = 2;
5093 while (*(args[cur_arg])) {
5094 if (!strcmp(args[cur_arg], "except")) {
5095 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005096 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005097 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5098 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005101 }
5102 /* flush useless bits */
5103 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005104 cur_arg += 2;
5105 } else if (!strcmp(args[cur_arg], "header")) {
5106 /* suboption header - needs additional argument for it */
5107 if (*(args[cur_arg+1]) == 0) {
5108 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5109 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005112 }
5113 free(curproxy->fwdfor_hdr_name);
5114 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5115 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5116 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005117 } else if (!strcmp(args[cur_arg], "if-none")) {
5118 curproxy->options &= ~PR_O_FF_ALWAYS;
5119 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005120 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005121 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005122 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005123 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005126 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005127 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005128 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005129 else if (!strcmp(args[1], "originalto")) {
5130 int cur_arg;
5131
5132 /* insert x-original-to field, but not for the IP address listed as an except.
5133 * set default options (ie: bitfield, header name, etc)
5134 */
5135
5136 curproxy->options |= PR_O_ORGTO;
5137
5138 free(curproxy->orgto_hdr_name);
5139 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5140 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5141
Willy Tarreau87cf5142011-08-19 22:57:24 +02005142 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005143 cur_arg = 2;
5144 while (*(args[cur_arg])) {
5145 if (!strcmp(args[cur_arg], "except")) {
5146 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005147 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 +02005148 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5149 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005152 }
5153 /* flush useless bits */
5154 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5155 cur_arg += 2;
5156 } else if (!strcmp(args[cur_arg], "header")) {
5157 /* suboption header - needs additional argument for it */
5158 if (*(args[cur_arg+1]) == 0) {
5159 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5160 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005161 err_code |= ERR_ALERT | ERR_FATAL;
5162 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005163 }
5164 free(curproxy->orgto_hdr_name);
5165 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5166 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5167 cur_arg += 2;
5168 } else {
5169 /* unknown suboption - catchall */
5170 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5171 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005174 }
5175 } /* end while loop */
5176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 else {
5178 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
Willy Tarreau93893792009-07-23 13:19:11 +02005182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005184 else if (!strcmp(args[0], "default_backend")) {
5185 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005186 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005187
5188 if (*(args[1]) == 0) {
5189 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005192 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005193 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005194 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005195
5196 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5197 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005200 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005202
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005203 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5204 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 +01005205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005207 /* enable reconnections to dispatch */
5208 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005209
5210 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005213 else if (!strcmp(args[0], "http-reuse")) {
5214 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5215 err_code |= ERR_WARN;
5216
5217 if (strcmp(args[1], "never") == 0) {
5218 /* enable a graceful server shutdown on an HTTP 404 response */
5219 curproxy->options &= ~PR_O_REUSE_MASK;
5220 curproxy->options |= PR_O_REUSE_NEVR;
5221 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5222 goto out;
5223 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005224 else if (strcmp(args[1], "safe") == 0) {
5225 /* enable a graceful server shutdown on an HTTP 404 response */
5226 curproxy->options &= ~PR_O_REUSE_MASK;
5227 curproxy->options |= PR_O_REUSE_SAFE;
5228 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5229 goto out;
5230 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005231 else if (strcmp(args[1], "aggressive") == 0) {
5232 curproxy->options &= ~PR_O_REUSE_MASK;
5233 curproxy->options |= PR_O_REUSE_AGGR;
5234 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5235 goto out;
5236 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005237 else if (strcmp(args[1], "always") == 0) {
5238 /* enable a graceful server shutdown on an HTTP 404 response */
5239 curproxy->options &= ~PR_O_REUSE_MASK;
5240 curproxy->options |= PR_O_REUSE_ALWS;
5241 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5242 goto out;
5243 }
5244 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005245 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005250 else if (!strcmp(args[0], "http-check")) {
5251 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005252 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005253
5254 if (strcmp(args[1], "disable-on-404") == 0) {
5255 /* enable a graceful server shutdown on an HTTP 404 response */
5256 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005257 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5258 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005259 }
Willy Tarreauef781042010-01-27 11:53:01 +01005260 else if (strcmp(args[1], "send-state") == 0) {
5261 /* enable emission of the apparent state of a server in HTTP checks */
5262 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005263 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5264 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005265 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005266 else if (strcmp(args[1], "expect") == 0) {
5267 const char *ptr_arg;
5268 int cur_arg;
5269
5270 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5271 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
5274 }
5275
5276 cur_arg = 2;
5277 /* consider exclamation marks, sole or at the beginning of a word */
5278 while (*(ptr_arg = args[cur_arg])) {
5279 while (*ptr_arg == '!') {
5280 curproxy->options2 ^= PR_O2_EXP_INV;
5281 ptr_arg++;
5282 }
5283 if (*ptr_arg)
5284 break;
5285 cur_arg++;
5286 }
5287 /* now ptr_arg points to the beginning of a word past any possible
5288 * exclamation mark, and cur_arg is the argument which holds this word.
5289 */
5290 if (strcmp(ptr_arg, "status") == 0) {
5291 if (!*(args[cur_arg + 1])) {
5292 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5293 file, linenum, args[0], args[1], ptr_arg);
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
5296 }
5297 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005298 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005299 curproxy->expect_str = strdup(args[cur_arg + 1]);
5300 }
5301 else if (strcmp(ptr_arg, "string") == 0) {
5302 if (!*(args[cur_arg + 1])) {
5303 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5304 file, linenum, args[0], args[1], ptr_arg);
5305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
5307 }
5308 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005309 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005310 curproxy->expect_str = strdup(args[cur_arg + 1]);
5311 }
5312 else if (strcmp(ptr_arg, "rstatus") == 0) {
5313 if (!*(args[cur_arg + 1])) {
5314 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5315 file, linenum, args[0], args[1], ptr_arg);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
5319 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005320 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005321 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005322 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005323 free(curproxy->expect_regex);
5324 curproxy->expect_regex = NULL;
5325 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005326 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005327 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5328 error = NULL;
5329 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5330 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5331 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5332 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 }
5337 else if (strcmp(ptr_arg, "rstring") == 0) {
5338 if (!*(args[cur_arg + 1])) {
5339 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5340 file, linenum, args[0], args[1], ptr_arg);
5341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
5343 }
5344 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005345 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005346 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005347 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005348 free(curproxy->expect_regex);
5349 curproxy->expect_regex = NULL;
5350 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005351 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005352 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5353 error = NULL;
5354 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5355 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5356 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5357 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
5360 }
5361 }
5362 else {
5363 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5364 file, linenum, args[0], args[1], ptr_arg);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005369 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005370 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 +02005371 err_code |= ERR_ALERT | ERR_FATAL;
5372 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005373 }
5374 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005375 else if (!strcmp(args[0], "tcp-check")) {
5376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5377 err_code |= ERR_WARN;
5378
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005379 if (strcmp(args[1], "comment") == 0) {
5380 int cur_arg;
5381 struct tcpcheck_rule *tcpcheck;
5382
5383 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005384 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005385 tcpcheck->action = TCPCHK_ACT_COMMENT;
5386
5387 if (!*args[cur_arg + 1]) {
5388 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5389 file, linenum, args[cur_arg]);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
5393
5394 tcpcheck->comment = strdup(args[cur_arg + 1]);
5395
5396 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005397 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5398 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005399 }
5400 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005401 const char *ptr_arg;
5402 int cur_arg;
5403 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005404
5405 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005406 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5407 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5408 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5409 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5410 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005411
Willy Tarreau5581c272015-05-13 12:24:53 +02005412 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5413 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5414 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5415 file, linenum);
5416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005418 }
5419
5420 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005421 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005422 tcpcheck->action = TCPCHK_ACT_CONNECT;
5423
5424 /* parsing each parameters to fill up the rule */
5425 while (*(ptr_arg = args[cur_arg])) {
5426 /* tcp port */
5427 if (strcmp(args[cur_arg], "port") == 0) {
5428 if ( (atol(args[cur_arg + 1]) > 65535) ||
5429 (atol(args[cur_arg + 1]) < 1) ){
5430 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5431 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435 tcpcheck->port = atol(args[cur_arg + 1]);
5436 cur_arg += 2;
5437 }
5438 /* send proxy protocol */
5439 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5440 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5441 cur_arg++;
5442 }
5443#ifdef USE_OPENSSL
5444 else if (strcmp(args[cur_arg], "ssl") == 0) {
5445 curproxy->options |= PR_O_TCPCHK_SSL;
5446 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5447 cur_arg++;
5448 }
5449#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005450 /* comment for this tcpcheck line */
5451 else if (strcmp(args[cur_arg], "comment") == 0) {
5452 if (!*args[cur_arg + 1]) {
5453 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5454 file, linenum, args[cur_arg]);
5455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
5458 tcpcheck->comment = strdup(args[cur_arg + 1]);
5459 cur_arg += 2;
5460 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005461 else {
5462#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005463 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 +01005464#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005465 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 +01005466#endif /* USE_OPENSSL */
5467 file, linenum, args[0], args[1], args[cur_arg]);
5468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
5470 }
5471
5472 }
5473
5474 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5475 }
5476 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005477 if (! *(args[2]) ) {
5478 /* SEND string expected */
5479 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5480 file, linenum, args[0], args[1], args[2]);
5481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
5483 } else {
5484 struct tcpcheck_rule *tcpcheck;
5485
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005486 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005487
5488 tcpcheck->action = TCPCHK_ACT_SEND;
5489 tcpcheck->string_len = strlen(args[2]);
5490 tcpcheck->string = strdup(args[2]);
5491 tcpcheck->expect_regex = NULL;
5492
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005493 /* comment for this tcpcheck line */
5494 if (strcmp(args[3], "comment") == 0) {
5495 if (!*args[4]) {
5496 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5497 file, linenum, args[3]);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
5500 }
5501 tcpcheck->comment = strdup(args[4]);
5502 }
5503
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005504 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5505 }
5506 }
5507 else if (strcmp(args[1], "send-binary") == 0) {
5508 if (! *(args[2]) ) {
5509 /* SEND binary string expected */
5510 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5511 file, linenum, args[0], args[1], args[2]);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 } else {
5515 struct tcpcheck_rule *tcpcheck;
5516 char *err = NULL;
5517
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005518 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005519
5520 tcpcheck->action = TCPCHK_ACT_SEND;
5521 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5522 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5523 file, linenum, args[0], args[1], args[2], err);
5524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526 }
5527 tcpcheck->expect_regex = NULL;
5528
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005529 /* comment for this tcpcheck line */
5530 if (strcmp(args[3], "comment") == 0) {
5531 if (!*args[4]) {
5532 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5533 file, linenum, args[3]);
5534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536 }
5537 tcpcheck->comment = strdup(args[4]);
5538 }
5539
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005540 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5541 }
5542 }
5543 else if (strcmp(args[1], "expect") == 0) {
5544 const char *ptr_arg;
5545 int cur_arg;
5546 int inverse = 0;
5547
5548 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5549 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
5552 }
5553
5554 cur_arg = 2;
5555 /* consider exclamation marks, sole or at the beginning of a word */
5556 while (*(ptr_arg = args[cur_arg])) {
5557 while (*ptr_arg == '!') {
5558 inverse = !inverse;
5559 ptr_arg++;
5560 }
5561 if (*ptr_arg)
5562 break;
5563 cur_arg++;
5564 }
5565 /* now ptr_arg points to the beginning of a word past any possible
5566 * exclamation mark, and cur_arg is the argument which holds this word.
5567 */
5568 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005569 struct tcpcheck_rule *tcpcheck;
5570 char *err = NULL;
5571
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005572 if (!*(args[cur_arg + 1])) {
5573 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5574 file, linenum, args[0], args[1], ptr_arg);
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
5577 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005578
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005579 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580
5581 tcpcheck->action = TCPCHK_ACT_EXPECT;
5582 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5583 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5584 file, linenum, args[0], args[1], args[2], err);
5585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
5587 }
5588 tcpcheck->expect_regex = NULL;
5589 tcpcheck->inverse = inverse;
5590
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005591 /* tcpcheck comment */
5592 cur_arg += 2;
5593 if (strcmp(args[cur_arg], "comment") == 0) {
5594 if (!*args[cur_arg + 1]) {
5595 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5596 file, linenum, args[cur_arg + 1]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600 tcpcheck->comment = strdup(args[cur_arg + 1]);
5601 }
5602
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005603 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5604 }
5605 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005606 struct tcpcheck_rule *tcpcheck;
5607
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005608 if (!*(args[cur_arg + 1])) {
5609 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5610 file, linenum, args[0], args[1], ptr_arg);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005614
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005615 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005616
5617 tcpcheck->action = TCPCHK_ACT_EXPECT;
5618 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5619 tcpcheck->string = strdup(args[cur_arg + 1]);
5620 tcpcheck->expect_regex = NULL;
5621 tcpcheck->inverse = inverse;
5622
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005623 /* tcpcheck comment */
5624 cur_arg += 2;
5625 if (strcmp(args[cur_arg], "comment") == 0) {
5626 if (!*args[cur_arg + 1]) {
5627 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5628 file, linenum, args[cur_arg + 1]);
5629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
5631 }
5632 tcpcheck->comment = strdup(args[cur_arg + 1]);
5633 }
5634
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005635 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5636 }
5637 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005638 struct tcpcheck_rule *tcpcheck;
5639
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005640 if (!*(args[cur_arg + 1])) {
5641 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5642 file, linenum, args[0], args[1], ptr_arg);
5643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
5645 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005646
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005647 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005648
5649 tcpcheck->action = TCPCHK_ACT_EXPECT;
5650 tcpcheck->string_len = 0;
5651 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005652 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5653 error = NULL;
5654 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5655 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5656 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5657 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005658 err_code |= ERR_ALERT | ERR_FATAL;
5659 goto out;
5660 }
5661 tcpcheck->inverse = inverse;
5662
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005663 /* tcpcheck comment */
5664 cur_arg += 2;
5665 if (strcmp(args[cur_arg], "comment") == 0) {
5666 if (!*args[cur_arg + 1]) {
5667 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5668 file, linenum, args[cur_arg + 1]);
5669 err_code |= ERR_ALERT | ERR_FATAL;
5670 goto out;
5671 }
5672 tcpcheck->comment = strdup(args[cur_arg + 1]);
5673 }
5674
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005675 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5676 }
5677 else {
5678 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5679 file, linenum, args[0], args[1], ptr_arg);
5680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
5683 }
5684 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005685 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
5688 }
5689 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005690 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005691 if (curproxy == &defproxy) {
5692 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005695 }
5696
Willy Tarreaub80c2302007-11-30 20:51:32 +01005697 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005698 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005699
5700 if (strcmp(args[1], "fail") == 0) {
5701 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005702 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005703 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5704 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005707 }
5708
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005709 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005710 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5711 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005714 }
5715 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5716 }
5717 else {
5718 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005721 }
5722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723#ifdef TPROXY
5724 else if (!strcmp(args[0], "transparent")) {
5725 /* enable transparent proxy connections */
5726 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005727 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 }
5730#endif
5731 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005732 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005734
Willy Tarreaubaaee002006-06-26 02:48:02 +02005735 if (*(args[1]) == 0) {
5736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005737 err_code |= ERR_ALERT | ERR_FATAL;
5738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 }
5740 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005741 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005744 else if (!strcmp(args[0], "backlog")) { /* backlog */
5745 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005747
5748 if (*(args[1]) == 0) {
5749 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= ERR_ALERT | ERR_FATAL;
5751 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005752 }
5753 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005754 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5755 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005756 }
Willy Tarreau86034312006-12-29 00:10:33 +01005757 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005759 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005760
Willy Tarreau86034312006-12-29 00:10:33 +01005761 if (*(args[1]) == 0) {
5762 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005765 }
5766 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005767 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5768 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5771 if (*(args[1]) == 0) {
5772 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005776 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5777 if (err) {
5778 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5779 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005780 err_code |= ERR_ALERT | ERR_FATAL;
5781 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005782 }
5783 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005784 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 }
5787 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005788 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005789 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005790 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005791
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 if (curproxy == &defproxy) {
5793 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005794 err_code |= ERR_ALERT | ERR_FATAL;
5795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005797 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005799
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005800 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005801 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005802 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005803 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005804 goto out;
5805 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005806
5807 proto = protocol_by_family(sk->ss_family);
5808 if (!proto || !proto->connect) {
5809 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5810 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005811 err_code |= ERR_ALERT | ERR_FATAL;
5812 goto out;
5813 }
5814
5815 if (port1 != port2) {
5816 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5817 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005818 err_code |= ERR_ALERT | ERR_FATAL;
5819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005821
5822 if (!port1) {
5823 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5824 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005825 err_code |= ERR_ALERT | ERR_FATAL;
5826 goto out;
5827 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005828
William Lallemanddf1425a2015-04-28 20:17:49 +02005829 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5830 goto out;
5831
Willy Tarreaud5191e72010-02-09 20:50:45 +01005832 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005833 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 }
5835 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005836 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005837 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005838
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005839 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5840 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005841 err_code |= ERR_ALERT | ERR_FATAL;
5842 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005845 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005846 /**
5847 * The syntax for hash-type config element is
5848 * hash-type {map-based|consistent} [[<algo>] avalanche]
5849 *
5850 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5851 */
5852 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005853
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5855 err_code |= ERR_WARN;
5856
5857 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005858 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5859 }
5860 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005861 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5862 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005863 else if (strcmp(args[1], "avalanche") == 0) {
5864 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]);
5865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005867 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005868 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005869 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005870 err_code |= ERR_ALERT | ERR_FATAL;
5871 goto out;
5872 }
Bhaskar98634f02013-10-29 23:30:51 -04005873
5874 /* set the hash function to use */
5875 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005876 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005877 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005878
5879 /* if consistent with no argument, then avalanche modifier is also applied */
5880 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5881 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005882 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005883 /* set the hash function */
5884 if (!strcmp(args[2], "sdbm")) {
5885 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5886 }
5887 else if (!strcmp(args[2], "djb2")) {
5888 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005889 }
5890 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005891 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005892 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005893 else if (!strcmp(args[2], "crc32")) {
5894 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5895 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005896 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005897 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 -05005898 err_code |= ERR_ALERT | ERR_FATAL;
5899 goto out;
5900 }
5901
5902 /* set the hash modifier */
5903 if (!strcmp(args[3], "avalanche")) {
5904 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5905 }
5906 else if (*args[3]) {
5907 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5908 err_code |= ERR_ALERT | ERR_FATAL;
5909 goto out;
5910 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005911 }
William Lallemanda73203e2012-03-12 12:48:57 +01005912 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005913 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5914 if (*(args[1]) == 0) {
5915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5916 err_code |= ERR_ALERT | ERR_FATAL;
5917 goto out;
5918 }
5919 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5920 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5921 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5922 err_code |= ERR_ALERT | ERR_FATAL;
5923 goto out;
5924 }
5925 }
William Lallemanda73203e2012-03-12 12:48:57 +01005926 else if (strcmp(args[0], "unique-id-format") == 0) {
5927 if (!*(args[1])) {
5928 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5929 err_code |= ERR_ALERT | ERR_FATAL;
5930 goto out;
5931 }
William Lallemand3203ff42012-11-11 17:30:56 +01005932 if (*(args[2])) {
5933 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
5936 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005937 free(curproxy->conf.uniqueid_format_string);
5938 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005939
Willy Tarreau62a61232013-04-12 18:13:46 +02005940 free(curproxy->conf.uif_file);
5941 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5942 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005943 }
William Lallemanda73203e2012-03-12 12:48:57 +01005944
5945 else if (strcmp(args[0], "unique-id-header") == 0) {
5946 if (!*(args[1])) {
5947 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5948 err_code |= ERR_ALERT | ERR_FATAL;
5949 goto out;
5950 }
5951 free(curproxy->header_unique_id);
5952 curproxy->header_unique_id = strdup(args[1]);
5953 }
5954
William Lallemand723b73a2012-02-08 16:37:49 +01005955 else if (strcmp(args[0], "log-format") == 0) {
5956 if (!*(args[1])) {
5957 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5958 err_code |= ERR_ALERT | ERR_FATAL;
5959 goto out;
5960 }
William Lallemand3203ff42012-11-11 17:30:56 +01005961 if (*(args[2])) {
5962 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5963 err_code |= ERR_ALERT | ERR_FATAL;
5964 goto out;
5965 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005966 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5967 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005968
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005969 if (curproxy->conf.logformat_string == default_http_log_format)
5970 oldlogformat = "option httplog";
5971 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5972 oldlogformat = "option tcplog";
5973 else if (curproxy->conf.logformat_string == clf_http_log_format)
5974 oldlogformat = "option httplog clf";
5975 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5976 file, linenum, oldlogformat);
5977 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005978 if (curproxy->conf.logformat_string != default_http_log_format &&
5979 curproxy->conf.logformat_string != default_tcp_log_format &&
5980 curproxy->conf.logformat_string != clf_http_log_format)
5981 free(curproxy->conf.logformat_string);
5982 curproxy->conf.logformat_string = strdup(args[1]);
5983
5984 free(curproxy->conf.lfs_file);
5985 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5986 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005987
5988 /* get a chance to improve log-format error reporting by
5989 * reporting the correct line-number when possible.
5990 */
5991 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5992 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5993 file, linenum, curproxy->id);
5994 err_code |= ERR_WARN;
5995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005997 else if (!strcmp(args[0], "log-format-sd")) {
5998 if (!*(args[1])) {
5999 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6000 err_code |= ERR_ALERT | ERR_FATAL;
6001 goto out;
6002 }
6003 if (*(args[2])) {
6004 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6005 err_code |= ERR_ALERT | ERR_FATAL;
6006 goto out;
6007 }
6008
6009 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6010 free(curproxy->conf.logformat_sd_string);
6011 curproxy->conf.logformat_sd_string = strdup(args[1]);
6012
6013 free(curproxy->conf.lfsd_file);
6014 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6015 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6016
6017 /* get a chance to improve log-format-sd error reporting by
6018 * reporting the correct line-number when possible.
6019 */
6020 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6021 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6022 file, linenum, curproxy->id);
6023 err_code |= ERR_WARN;
6024 }
6025 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006026 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6027 if (*(args[1]) == 0) {
6028 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6029 err_code |= ERR_ALERT | ERR_FATAL;
6030 goto out;
6031 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006032 chunk_destroy(&curproxy->log_tag);
6033 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006034 }
William Lallemand0f99e342011-10-12 17:50:54 +02006035 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6036 /* delete previous herited or defined syslog servers */
6037 struct logsrv *back;
6038
6039 if (*(args[1]) != 0) {
6040 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6041 err_code |= ERR_ALERT | ERR_FATAL;
6042 goto out;
6043 }
6044
William Lallemand723b73a2012-02-08 16:37:49 +01006045 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6046 LIST_DEL(&tmplogsrv->list);
6047 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006048 }
6049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006050 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006051 struct logsrv *logsrv;
6052
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006054 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006055 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006056 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006057 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006058 LIST_INIT(&node->list);
6059 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061 }
6062 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006063 struct sockaddr_storage *sk;
6064 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006065 int arg = 0;
6066 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006067
Vincent Bernat02779b62016-04-03 13:48:43 +02006068 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069
Willy Tarreau18324f52014-06-27 18:10:07 +02006070 /* just after the address, a length may be specified */
6071 if (strcmp(args[arg+2], "len") == 0) {
6072 len = atoi(args[arg+3]);
6073 if (len < 80 || len > 65535) {
6074 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6075 file, linenum, args[arg+3]);
6076 err_code |= ERR_ALERT | ERR_FATAL;
6077 goto out;
6078 }
6079 logsrv->maxlen = len;
6080
6081 /* skip these two args */
6082 arg += 2;
6083 }
6084 else
6085 logsrv->maxlen = MAX_SYSLOG_LEN;
6086
Christopher Faulet084aa962017-08-29 16:54:41 +02006087 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006088 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006089
Dragan Dosen1322d092015-09-22 16:05:32 +02006090 /* after the length, a format may be specified */
6091 if (strcmp(args[arg+2], "format") == 0) {
6092 logsrv->format = get_log_format(args[arg+3]);
6093 if (logsrv->format < 0) {
6094 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
6097 }
6098
6099 /* skip these two args */
6100 arg += 2;
6101 }
6102
William Lallemanddf1425a2015-04-28 20:17:49 +02006103 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6104 goto out;
6105
Willy Tarreau18324f52014-06-27 18:10:07 +02006106 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006107 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006108 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006109 err_code |= ERR_ALERT | ERR_FATAL;
6110 goto out;
6111
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 }
6113
William Lallemand0f99e342011-10-12 17:50:54 +02006114 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006115 if (*(args[arg+3])) {
6116 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006117 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006118 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006119 err_code |= ERR_ALERT | ERR_FATAL;
6120 goto out;
6121
Willy Tarreaubaaee002006-06-26 02:48:02 +02006122 }
6123 }
6124
William Lallemand0f99e342011-10-12 17:50:54 +02006125 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006126 if (*(args[arg+4])) {
6127 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006128 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006129 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006130 err_code |= ERR_ALERT | ERR_FATAL;
6131 goto out;
6132
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006133 }
6134 }
6135
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006136 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006137 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006138 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006139 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006140 goto out;
6141 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006142
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006143 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006144
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006145 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006146 if (port1 != port2) {
6147 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6148 file, linenum, args[0], args[1]);
6149 err_code |= ERR_ALERT | ERR_FATAL;
6150 goto out;
6151 }
6152
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006153 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006154 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 }
William Lallemand0f99e342011-10-12 17:50:54 +02006156
6157 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 }
6159 else {
6160 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6161 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006162 err_code |= ERR_ALERT | ERR_FATAL;
6163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 }
6165 }
6166 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006167 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006168 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006169 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006170 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006171
Willy Tarreau977b8e42006-12-29 14:19:17 +01006172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006173 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006174
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006176 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6177 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006178 err_code |= ERR_ALERT | ERR_FATAL;
6179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006180 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006181
6182 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006183 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6184 free(curproxy->conn_src.iface_name);
6185 curproxy->conn_src.iface_name = NULL;
6186 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006187
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006188 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006189 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006190 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006191 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006192 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006193 goto out;
6194 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006195
6196 proto = protocol_by_family(sk->ss_family);
6197 if (!proto || !proto->connect) {
6198 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006199 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
6202 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006203
6204 if (port1 != port2) {
6205 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6206 file, linenum, args[0], args[1]);
6207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
6209 }
6210
Willy Tarreauef9a3602012-12-08 22:29:20 +01006211 curproxy->conn_src.source_addr = *sk;
6212 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006213
6214 cur_arg = 2;
6215 while (*(args[cur_arg])) {
6216 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006217#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006218 if (!*args[cur_arg + 1]) {
6219 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6220 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006221 err_code |= ERR_ALERT | ERR_FATAL;
6222 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006223 }
6224
6225 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006226 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6227 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006228 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006229 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6230 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006231 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6232 char *name, *end;
6233
6234 name = args[cur_arg+1] + 7;
6235 while (isspace(*name))
6236 name++;
6237
6238 end = name;
6239 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6240 end++;
6241
Willy Tarreauef9a3602012-12-08 22:29:20 +01006242 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6243 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6244 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6245 curproxy->conn_src.bind_hdr_len = end - name;
6246 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6247 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6248 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006249
6250 /* now look for an occurrence number */
6251 while (isspace(*end))
6252 end++;
6253 if (*end == ',') {
6254 end++;
6255 name = end;
6256 if (*end == '-')
6257 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006258 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006259 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006260 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006261 }
6262
Willy Tarreauef9a3602012-12-08 22:29:20 +01006263 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006264 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6265 " occurrences values smaller than %d.\n",
6266 file, linenum, MAX_HDR_HISTORY);
6267 err_code |= ERR_ALERT | ERR_FATAL;
6268 goto out;
6269 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006270 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006271 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006272
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006273 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006274 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006275 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006276 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006277 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006278 goto out;
6279 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006280
6281 proto = protocol_by_family(sk->ss_family);
6282 if (!proto || !proto->connect) {
6283 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6284 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006285 err_code |= ERR_ALERT | ERR_FATAL;
6286 goto out;
6287 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006288
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006289 if (port1 != port2) {
6290 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6291 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006292 err_code |= ERR_ALERT | ERR_FATAL;
6293 goto out;
6294 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006295 curproxy->conn_src.tproxy_addr = *sk;
6296 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006297 }
6298 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006299#else /* no TPROXY support */
6300 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006301 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006302 err_code |= ERR_ALERT | ERR_FATAL;
6303 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006304#endif
6305 cur_arg += 2;
6306 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006307 }
6308
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006309 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6310#ifdef SO_BINDTODEVICE
6311 if (!*args[cur_arg + 1]) {
6312 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6313 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006316 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006317 free(curproxy->conn_src.iface_name);
6318 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6319 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006320 global.last_checks |= LSTCHK_NETADM;
6321#else
6322 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6323 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006324 err_code |= ERR_ALERT | ERR_FATAL;
6325 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006326#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006327 cur_arg += 2;
6328 continue;
6329 }
6330 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006331 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006332 err_code |= ERR_ALERT | ERR_FATAL;
6333 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006336 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6337 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6338 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006339 err_code |= ERR_ALERT | ERR_FATAL;
6340 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006343 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006346 err_code |= ERR_ALERT | ERR_FATAL;
6347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349
6350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006351 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006352 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
6356 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006358 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
6363 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006365 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006366 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369 }
6370 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006372 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006373 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 }
6377 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006379 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006380 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006384 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006386 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006387 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006389 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006392 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6394 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006395 err_code |= ERR_ALERT | ERR_FATAL;
6396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006398
6399 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006400 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006401 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 }
6405 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006407 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006408 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 }
6412 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006414 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006415 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 }
6419 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006420 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006421 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006422 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006423 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 }
6426 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006428 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006429 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006432 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006433 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006434 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006435 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006436 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006437 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006438 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006441 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006442
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 if (curproxy == &defproxy) {
6444 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006445 err_code |= ERR_ALERT | ERR_FATAL;
6446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006448 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006449 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451 if (*(args[1]) == 0) {
6452 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006456
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006457 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006458 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006459 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6460 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006461 err_code |= ERR_ALERT | ERR_FATAL;
6462 goto out;
6463 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006464 err_code |= warnif_cond_conflicts(cond,
6465 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6466 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006467 }
6468 else if (*args[2]) {
6469 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6470 file, linenum, args[0], args[2]);
6471 err_code |= ERR_ALERT | ERR_FATAL;
6472 goto out;
6473 }
6474
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006475 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006476 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006477 wl->s = strdup(args[1]);
6478 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006479 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 }
6481 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006482 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6484 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006485 err_code |= ERR_ALERT | ERR_FATAL;
6486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006488
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006490 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006491 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494 }
6495 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006497 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006498 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 }
6502 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006504 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006505 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 }
6509 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6512 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006513 err_code |= ERR_ALERT | ERR_FATAL;
6514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006515 }
6516
Willy Tarreauade5ec42010-01-28 19:33:49 +01006517 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006518 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006519 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006520 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522 }
6523 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006524 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006525 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006526 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006527 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 }
6530 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006531 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006532 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006533 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006534 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006536 }
6537 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006538 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006539
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 if (curproxy == &defproxy) {
6541 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006542 err_code |= ERR_ALERT | ERR_FATAL;
6543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006545 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006546 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548 if (*(args[1]) == 0) {
6549 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006550 err_code |= ERR_ALERT | ERR_FATAL;
6551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 }
6553
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006554 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006555 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006556 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6557 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006558 err_code |= ERR_ALERT | ERR_FATAL;
6559 goto out;
6560 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006561 err_code |= warnif_cond_conflicts(cond,
6562 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6563 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006564 }
6565 else if (*args[2]) {
6566 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6567 file, linenum, args[0], args[2]);
6568 err_code |= ERR_ALERT | ERR_FATAL;
6569 goto out;
6570 }
6571
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006572 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006573 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006574 wl->s = strdup(args[1]);
6575 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006576 }
6577 else if (!strcmp(args[0], "errorloc") ||
6578 !strcmp(args[0], "errorloc302") ||
6579 !strcmp(args[0], "errorloc303")) { /* error location */
6580 int errnum, errlen;
6581 char *err;
6582
Willy Tarreau977b8e42006-12-29 14:19:17 +01006583 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006584 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006585
Willy Tarreaubaaee002006-06-26 02:48:02 +02006586 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006587 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006588 err_code |= ERR_ALERT | ERR_FATAL;
6589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590 }
6591
6592 errnum = atol(args[1]);
6593 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006594 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6595 err = malloc(errlen);
6596 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006597 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006598 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6599 err = malloc(errlen);
6600 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006601 }
6602
Willy Tarreau0f772532006-12-23 20:51:41 +01006603 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6604 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006605 chunk_destroy(&curproxy->errmsg[rc]);
6606 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006607 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006610
6611 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006612 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6613 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006614 free(err);
6615 }
6616 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006617 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6618 int errnum, errlen, fd;
6619 char *err;
6620 struct stat stat;
6621
6622 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006623 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006624
6625 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006626 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006627 err_code |= ERR_ALERT | ERR_FATAL;
6628 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006629 }
6630
6631 fd = open(args[2], O_RDONLY);
6632 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6633 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6634 file, linenum, args[2], args[1]);
6635 if (fd >= 0)
6636 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006637 err_code |= ERR_ALERT | ERR_FATAL;
6638 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006639 }
6640
Willy Tarreau27a674e2009-08-17 07:23:33 +02006641 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006642 errlen = stat.st_size;
6643 } else {
6644 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006645 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006646 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006647 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006648 }
6649
6650 err = malloc(errlen); /* malloc() must succeed during parsing */
6651 errnum = read(fd, err, errlen);
6652 if (errnum != errlen) {
6653 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6654 file, linenum, args[2], args[1]);
6655 close(fd);
6656 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006657 err_code |= ERR_ALERT | ERR_FATAL;
6658 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006659 }
6660 close(fd);
6661
6662 errnum = atol(args[1]);
6663 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6664 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006665 chunk_destroy(&curproxy->errmsg[rc]);
6666 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006667 break;
6668 }
6669 }
6670
6671 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006672 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6673 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006674 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006675 free(err);
6676 }
6677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006678 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006679 struct cfg_kw_list *kwl;
6680 int index;
6681
6682 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6683 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6684 if (kwl->kw[index].section != CFG_LISTEN)
6685 continue;
6686 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6687 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006688 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006689 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006690 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006691 err_code |= ERR_ALERT | ERR_FATAL;
6692 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006693 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006694 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006695 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006696 err_code |= ERR_WARN;
6697 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006698 }
Willy Tarreau93893792009-07-23 13:19:11 +02006699 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006700 }
6701 }
6702 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006703
Willy Tarreau6daf3432008-01-22 16:44:08 +01006704 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006705 err_code |= ERR_ALERT | ERR_FATAL;
6706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006707 }
Willy Tarreau93893792009-07-23 13:19:11 +02006708 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006709 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006710 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006711}
6712
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006713int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006714cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6715{
6716#ifdef CONFIG_HAP_NS
6717 const char *err;
6718 const char *item = args[0];
6719
6720 if (!strcmp(item, "namespace_list")) {
6721 return 0;
6722 }
6723 else if (!strcmp(item, "namespace")) {
6724 size_t idx = 1;
6725 const char *current;
6726 while (*(current = args[idx++])) {
6727 err = invalid_char(current);
6728 if (err) {
6729 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6730 file, linenum, *err, item, current);
6731 return ERR_ALERT | ERR_FATAL;
6732 }
6733
6734 if (netns_store_lookup(current, strlen(current))) {
6735 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6736 file, linenum, current);
6737 return ERR_ALERT | ERR_FATAL;
6738 }
6739 if (!netns_store_insert(current)) {
6740 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6741 file, linenum, current);
6742 return ERR_ALERT | ERR_FATAL;
6743 }
6744 }
6745 }
6746
6747 return 0;
6748#else
6749 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6750 file, linenum);
6751 return ERR_ALERT | ERR_FATAL;
6752#endif
6753}
6754
6755int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006756cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6757{
6758
6759 int err_code = 0;
6760 const char *err;
6761
6762 if (!strcmp(args[0], "userlist")) { /* new userlist */
6763 struct userlist *newul;
6764
6765 if (!*args[1]) {
6766 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6767 file, linenum, args[0]);
6768 err_code |= ERR_ALERT | ERR_FATAL;
6769 goto out;
6770 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006771 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6772 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006773
6774 err = invalid_char(args[1]);
6775 if (err) {
6776 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6777 file, linenum, *err, args[0], args[1]);
6778 err_code |= ERR_ALERT | ERR_FATAL;
6779 goto out;
6780 }
6781
6782 for (newul = userlist; newul; newul = newul->next)
6783 if (!strcmp(newul->name, args[1])) {
6784 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6785 file, linenum, args[1]);
6786 err_code |= ERR_WARN;
6787 goto out;
6788 }
6789
Vincent Bernat02779b62016-04-03 13:48:43 +02006790 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006791 if (!newul) {
6792 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6793 err_code |= ERR_ALERT | ERR_ABORT;
6794 goto out;
6795 }
6796
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006797 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006798 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006799 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6800 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006801 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802 goto out;
6803 }
6804
6805 newul->next = userlist;
6806 userlist = newul;
6807
6808 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006809 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006810 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006811 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006812
6813 if (!*args[1]) {
6814 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6815 file, linenum, args[0]);
6816 err_code |= ERR_ALERT | ERR_FATAL;
6817 goto out;
6818 }
6819
6820 err = invalid_char(args[1]);
6821 if (err) {
6822 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6823 file, linenum, *err, args[0], args[1]);
6824 err_code |= ERR_ALERT | ERR_FATAL;
6825 goto out;
6826 }
6827
William Lallemand4ac9f542015-05-28 18:03:51 +02006828 if (!userlist)
6829 goto out;
6830
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006831 for (ag = userlist->groups; ag; ag = ag->next)
6832 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006833 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6834 file, linenum, args[1], userlist->name);
6835 err_code |= ERR_ALERT;
6836 goto out;
6837 }
6838
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006839 ag = calloc(1, sizeof(*ag));
6840 if (!ag) {
6841 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6842 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006843 goto out;
6844 }
6845
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006846 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006847 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006848 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6849 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006850 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006851 goto out;
6852 }
6853
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006854 cur_arg = 2;
6855
6856 while (*args[cur_arg]) {
6857 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006858 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006859 cur_arg += 2;
6860 continue;
6861 } else {
6862 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6863 file, linenum, args[0]);
6864 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006865 free(ag->groupusers);
6866 free(ag->name);
6867 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006868 goto out;
6869 }
6870 }
6871
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006872 ag->next = userlist->groups;
6873 userlist->groups = ag;
6874
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006875 } else if (!strcmp(args[0], "user")) { /* new user */
6876 struct auth_users *newuser;
6877 int cur_arg;
6878
6879 if (!*args[1]) {
6880 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6881 file, linenum, args[0]);
6882 err_code |= ERR_ALERT | ERR_FATAL;
6883 goto out;
6884 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006885 if (!userlist)
6886 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006887
6888 for (newuser = userlist->users; newuser; newuser = newuser->next)
6889 if (!strcmp(newuser->user, args[1])) {
6890 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6891 file, linenum, args[1], userlist->name);
6892 err_code |= ERR_ALERT;
6893 goto out;
6894 }
6895
Vincent Bernat02779b62016-04-03 13:48:43 +02006896 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006897 if (!newuser) {
6898 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6899 err_code |= ERR_ALERT | ERR_ABORT;
6900 goto out;
6901 }
6902
6903 newuser->user = strdup(args[1]);
6904
6905 newuser->next = userlist->users;
6906 userlist->users = newuser;
6907
6908 cur_arg = 2;
6909
6910 while (*args[cur_arg]) {
6911 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006912#ifdef CONFIG_HAP_CRYPT
6913 if (!crypt("", args[cur_arg + 1])) {
6914 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6915 file, linenum, newuser->user);
6916 err_code |= ERR_ALERT | ERR_FATAL;
6917 goto out;
6918 }
6919#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006920 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6921 file, linenum);
6922 err_code |= ERR_ALERT;
6923#endif
6924 newuser->pass = strdup(args[cur_arg + 1]);
6925 cur_arg += 2;
6926 continue;
6927 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6928 newuser->pass = strdup(args[cur_arg + 1]);
6929 newuser->flags |= AU_O_INSECURE;
6930 cur_arg += 2;
6931 continue;
6932 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006933 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006934 cur_arg += 2;
6935 continue;
6936 } else {
6937 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6938 file, linenum, args[0]);
6939 err_code |= ERR_ALERT | ERR_FATAL;
6940 goto out;
6941 }
6942 }
6943 } else {
6944 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6945 err_code |= ERR_ALERT | ERR_FATAL;
6946 }
6947
6948out:
6949 return err_code;
6950}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006951
Christopher Faulet79bdef32016-11-04 22:36:15 +01006952int
6953cfg_parse_scope(const char *file, int linenum, char *line)
6954{
6955 char *beg, *end, *scope = NULL;
6956 int err_code = 0;
6957 const char *err;
6958
6959 beg = line + 1;
6960 end = strchr(beg, ']');
6961
6962 /* Detect end of scope declaration */
6963 if (!end || end == beg) {
6964 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6965 file, linenum);
6966 err_code |= ERR_ALERT | ERR_FATAL;
6967 goto out;
6968 }
6969
6970 /* Get scope name and check its validity */
6971 scope = my_strndup(beg, end-beg);
6972 err = invalid_char(scope);
6973 if (err) {
6974 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6975 file, linenum, *err);
6976 err_code |= ERR_ALERT | ERR_ABORT;
6977 goto out;
6978 }
6979
6980 /* Be sure to have a scope declaration alone on its line */
6981 line = end+1;
6982 while (isspace((unsigned char)*line))
6983 line++;
6984 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6985 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6986 file, linenum, *line);
6987 err_code |= ERR_ALERT | ERR_ABORT;
6988 goto out;
6989 }
6990
6991 /* We have a valid scope declaration, save it */
6992 free(cfg_scope);
6993 cfg_scope = scope;
6994 scope = NULL;
6995
6996 out:
6997 free(scope);
6998 return err_code;
6999}
7000
Willy Tarreaubaaee002006-06-26 02:48:02 +02007001/*
7002 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007003 * Returns the error code, 0 if OK, or any combination of :
7004 * - ERR_ABORT: must abort ASAP
7005 * - ERR_FATAL: we can continue parsing but not start the service
7006 * - ERR_WARN: a warning has been emitted
7007 * - ERR_ALERT: an alert has been emitted
7008 * Only the two first ones can stop processing, the two others are just
7009 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007011int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007012{
William Lallemand64e84512015-05-12 14:25:37 +02007013 char *thisline;
7014 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007015 FILE *f;
7016 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007017 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007018 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007019 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007020 int readbytes = 0;
7021
7022 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007023 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007024 return -1;
7025 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007026
David Carlier97880bb2016-04-08 10:35:26 +01007027 if ((f=fopen(file,"r")) == NULL) {
7028 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007029 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007031
William Lallemandb2f07452015-05-12 14:27:13 +02007032next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007033 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007034 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007035 char *end;
7036 char *args[MAX_LINE_ARGS + 1];
7037 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007038 int dquote = 0; /* double quote */
7039 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007040
Willy Tarreaubaaee002006-06-26 02:48:02 +02007041 linenum++;
7042
7043 end = line + strlen(line);
7044
William Lallemand64e84512015-05-12 14:25:37 +02007045 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007046 /* Check if we reached the limit and the last char is not \n.
7047 * Watch out for the last line without the terminating '\n'!
7048 */
William Lallemand64e84512015-05-12 14:25:37 +02007049 char *newline;
7050 int newlinesize = linesize * 2;
7051
7052 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7053 if (newline == NULL) {
7054 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7055 file, linenum);
7056 err_code |= ERR_ALERT | ERR_FATAL;
7057 continue;
7058 }
7059
7060 readbytes = linesize - 1;
7061 linesize = newlinesize;
7062 thisline = newline;
7063 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007064 }
7065
William Lallemand64e84512015-05-12 14:25:37 +02007066 readbytes = 0;
7067
Willy Tarreaubaaee002006-06-26 02:48:02 +02007068 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007069 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007070 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007071
Christopher Faulet79bdef32016-11-04 22:36:15 +01007072
7073 if (*line == '[') {/* This is the begining if a scope */
7074 err_code |= cfg_parse_scope(file, linenum, line);
7075 goto next_line;
7076 }
7077
Willy Tarreaubaaee002006-06-26 02:48:02 +02007078 arg = 0;
7079 args[arg] = line;
7080
7081 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007082 if (*line == '"' && !squote) { /* double quote outside single quotes */
7083 if (dquote)
7084 dquote = 0;
7085 else
7086 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007087 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007088 end--;
7089 }
7090 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7091 if (squote)
7092 squote = 0;
7093 else
7094 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007095 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007096 end--;
7097 }
7098 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007099 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7100 * C equivalent value. Other combinations left unchanged (eg: \1).
7101 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102 int skip = 0;
7103 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7104 *line = line[1];
7105 skip = 1;
7106 }
7107 else if (line[1] == 'r') {
7108 *line = '\r';
7109 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007111 else if (line[1] == 'n') {
7112 *line = '\n';
7113 skip = 1;
7114 }
7115 else if (line[1] == 't') {
7116 *line = '\t';
7117 skip = 1;
7118 }
7119 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007120 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007121 unsigned char hex1, hex2;
7122 hex1 = toupper(line[2]) - '0';
7123 hex2 = toupper(line[3]) - '0';
7124 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7125 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7126 *line = (hex1<<4) + hex2;
7127 skip = 3;
7128 }
7129 else {
7130 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007131 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007132 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007133 } else if (line[1] == '"') {
7134 *line = '"';
7135 skip = 1;
7136 } else if (line[1] == '\'') {
7137 *line = '\'';
7138 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007139 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7140 *line = '$';
7141 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007142 }
7143 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007144 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007145 end -= skip;
7146 }
7147 line++;
7148 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007149 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007150 /* end of string, end of loop */
7151 *line = 0;
7152 break;
7153 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007154 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007155 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007156 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007157 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007158 line++;
7159 args[++arg] = line;
7160 }
William Lallemandb2f07452015-05-12 14:27:13 +02007161 else if (dquote && *line == '$') {
7162 /* environment variables are evaluated inside double quotes */
7163 char *var_beg;
7164 char *var_end;
7165 char save_char;
7166 char *value;
7167 int val_len;
7168 int newlinesize;
7169 int braces = 0;
7170
7171 var_beg = line + 1;
7172 var_end = var_beg;
7173
7174 if (*var_beg == '{') {
7175 var_beg++;
7176 var_end++;
7177 braces = 1;
7178 }
7179
7180 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7181 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7182 err_code |= ERR_ALERT | ERR_FATAL;
7183 goto next_line; /* skip current line */
7184 }
7185
7186 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7187 var_end++;
7188
7189 save_char = *var_end;
7190 *var_end = '\0';
7191 value = getenv(var_beg);
7192 *var_end = save_char;
7193 val_len = value ? strlen(value) : 0;
7194
7195 if (braces) {
7196 if (*var_end == '}') {
7197 var_end++;
7198 braces = 0;
7199 } else {
7200 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7201 err_code |= ERR_ALERT | ERR_FATAL;
7202 goto next_line; /* skip current line */
7203 }
7204 }
7205
7206 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7207
7208 /* if not enough space in thisline */
7209 if (newlinesize > linesize) {
7210 char *newline;
7211
7212 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7213 if (newline == NULL) {
7214 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7215 err_code |= ERR_ALERT | ERR_FATAL;
7216 goto next_line; /* slip current line */
7217 }
7218 /* recompute pointers if realloc returns a new pointer */
7219 if (newline != thisline) {
7220 int i;
7221 int diff;
7222
7223 for (i = 0; i <= arg; i++) {
7224 diff = args[i] - thisline;
7225 args[i] = newline + diff;
7226 }
7227
7228 diff = var_end - thisline;
7229 var_end = newline + diff;
7230 diff = end - thisline;
7231 end = newline + diff;
7232 diff = line - thisline;
7233 line = newline + diff;
7234 thisline = newline;
7235 }
7236 linesize = newlinesize;
7237 }
7238
7239 /* insert value inside the line */
7240 memmove(line + val_len, var_end, end - var_end + 1);
7241 memcpy(line, value, val_len);
7242 end += val_len - (var_end - line);
7243 line += val_len;
7244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007245 else {
7246 line++;
7247 }
7248 }
William Lallemandb2f07452015-05-12 14:27:13 +02007249
William Lallemandf9873ba2015-05-05 17:37:14 +02007250 if (dquote) {
7251 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7252 err_code |= ERR_ALERT | ERR_FATAL;
7253 }
7254
7255 if (squote) {
7256 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7257 err_code |= ERR_ALERT | ERR_FATAL;
7258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007259
7260 /* empty line */
7261 if (!**args)
7262 continue;
7263
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007264 if (*line) {
7265 /* we had to stop due to too many args.
7266 * Let's terminate the string, print the offending part then cut the
7267 * last arg.
7268 */
7269 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7270 line++;
7271 *line = '\0';
7272
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007273 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007274 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007275 err_code |= ERR_ALERT | ERR_FATAL;
7276 args[arg] = line;
7277 }
7278
Willy Tarreau540abe42007-05-02 20:50:16 +02007279 /* zero out remaining args and ensure that at least one entry
7280 * is zeroed out.
7281 */
7282 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007283 args[arg] = line;
7284 }
7285
Willy Tarreau3842f002009-06-14 11:39:52 +02007286 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007287 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007288 char *tmp;
7289
Willy Tarreau3842f002009-06-14 11:39:52 +02007290 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007291 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007292 for (arg=0; *args[arg+1]; arg++)
7293 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007294 *tmp = '\0'; // fix the next arg to \0
7295 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007296 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007297 else if (!strcmp(args[0], "default")) {
7298 kwm = KWM_DEF;
7299 for (arg=0; *args[arg+1]; arg++)
7300 args[arg] = args[arg+1]; // shift args after inversion
7301 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007302
William Lallemand0f99e342011-10-12 17:50:54 +02007303 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7304 strcmp(args[0], "log") != 0) {
7305 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007306 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007307 }
7308
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007309 /* detect section start */
7310 list_for_each_entry(ics, &sections, list) {
7311 if (strcmp(args[0], ics->section_name) == 0) {
7312 cursection = ics->section_name;
7313 cs = ics;
7314 break;
7315 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007316 }
7317
William Lallemandd2ff56d2017-10-16 11:06:50 +02007318 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007319 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007320 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007321 } else {
7322 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007323
William Lallemandd2ff56d2017-10-16 11:06:50 +02007324 if (pcs != cs && pcs && pcs->post_section_parser) {
7325 err_code |= pcs->post_section_parser();
7326 if (err_code & ERR_ABORT)
7327 goto err;
7328 }
7329
7330 err_code |= cs->section_parser(file, linenum, args, kwm);
7331 if (err_code & ERR_ABORT)
7332 goto err;
7333 }
7334 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007335 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007336
7337 if (pcs == cs && pcs && pcs->post_section_parser)
7338 err_code |= pcs->post_section_parser();
7339
7340err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007341 free(cfg_scope);
7342 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007343 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007344 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007345 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007346 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007347}
7348
Willy Tarreau64ab6072014-09-16 12:17:36 +02007349/* This function propagates processes from frontend <from> to backend <to> so
7350 * that it is always guaranteed that a backend pointed to by a frontend is
7351 * bound to all of its processes. After that, if the target is a "listen"
7352 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007353 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007354 * checked first to ensure that <to> is already bound to all processes of
7355 * <from>, there is no risk of looping and we ensure to follow the shortest
7356 * path to the destination.
7357 *
7358 * It is possible to set <to> to NULL for the first call so that the function
7359 * takes care of visiting the initial frontend in <from>.
7360 *
7361 * It is important to note that the function relies on the fact that all names
7362 * have already been resolved.
7363 */
7364void propagate_processes(struct proxy *from, struct proxy *to)
7365{
7366 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007367
7368 if (to) {
7369 /* check whether we need to go down */
7370 if (from->bind_proc &&
7371 (from->bind_proc & to->bind_proc) == from->bind_proc)
7372 return;
7373
7374 if (!from->bind_proc && !to->bind_proc)
7375 return;
7376
7377 to->bind_proc = from->bind_proc ?
7378 (to->bind_proc | from->bind_proc) : 0;
7379
7380 /* now propagate down */
7381 from = to;
7382 }
7383
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007384 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007385 return;
7386
Willy Tarreauf6b70012014-12-18 14:00:43 +01007387 if (from->state == PR_STSTOPPED)
7388 return;
7389
Willy Tarreau64ab6072014-09-16 12:17:36 +02007390 /* default_backend */
7391 if (from->defbe.be)
7392 propagate_processes(from, from->defbe.be);
7393
7394 /* use_backend */
7395 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007396 if (rule->dynamic)
7397 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007398 to = rule->be.backend;
7399 propagate_processes(from, to);
7400 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007401}
7402
Willy Tarreaubb925012009-07-23 13:36:36 +02007403/*
7404 * Returns the error code, 0 if OK, or any combination of :
7405 * - ERR_ABORT: must abort ASAP
7406 * - ERR_FATAL: we can continue parsing but not start the service
7407 * - ERR_WARN: a warning has been emitted
7408 * - ERR_ALERT: an alert has been emitted
7409 * Only the two first ones can stop processing, the two others are just
7410 * indicators.
7411 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007412int check_config_validity()
7413{
7414 int cfgerr = 0;
7415 struct proxy *curproxy = NULL;
7416 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007417 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007418 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007419 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007420 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007421 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007422
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007423 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007424 /*
7425 * Now, check for the integrity of all that we have collected.
7426 */
7427
7428 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007429 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007430
Willy Tarreau193b8c62012-11-22 00:17:38 +01007431 if (!global.tune.max_http_hdr)
7432 global.tune.max_http_hdr = MAX_HTTP_HDR;
7433
7434 if (!global.tune.cookie_len)
7435 global.tune.cookie_len = CAPTURE_LEN;
7436
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007437 if (!global.tune.requri_len)
7438 global.tune.requri_len = REQURI_LEN;
7439
Emeric Brun96fd9262017-07-05 13:33:16 +02007440 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7441
Willy Tarreau193b8c62012-11-22 00:17:38 +01007442 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7443
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007444 /* Post initialisation of the users and groups lists. */
7445 err_code = userlist_postinit();
7446 if (err_code != ERR_NONE)
7447 goto out;
7448
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007449 /* first, we will invert the proxy list order */
7450 curproxy = NULL;
7451 while (proxy) {
7452 struct proxy *next;
7453
7454 next = proxy->next;
7455 proxy->next = curproxy;
7456 curproxy = proxy;
7457 if (!next)
7458 break;
7459 proxy = next;
7460 }
7461
Willy Tarreau419ead82014-09-16 13:41:21 +02007462 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007463 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007464 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007465 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007466 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007467 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007468 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007469 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007470
Willy Tarreau050536d2012-10-04 08:47:34 +02007471 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007472 /* proxy ID not set, use automatic numbering with first
7473 * spare entry starting with next_pxid.
7474 */
7475 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7476 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7477 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007478 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007479 next_pxid++;
7480
Willy Tarreau55ea7572007-06-17 19:56:27 +02007481
Willy Tarreaubaaee002006-06-26 02:48:02 +02007482 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007483 /* ensure we don't keep listeners uselessly bound */
7484 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007485 free((void *)curproxy->table.peers.name);
7486 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007487 continue;
7488 }
7489
Willy Tarreau102df612014-05-07 23:56:38 +02007490 /* Check multi-process mode compatibility for the current proxy */
7491
7492 if (curproxy->bind_proc) {
7493 /* an explicit bind-process was specified, let's check how many
7494 * processes remain.
7495 */
David Carliere6c39412015-07-02 07:00:17 +00007496 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007497
7498 curproxy->bind_proc &= nbits(global.nbproc);
7499 if (!curproxy->bind_proc && nbproc == 1) {
7500 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);
7501 curproxy->bind_proc = 1;
7502 }
7503 else if (!curproxy->bind_proc && nbproc > 1) {
7504 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);
7505 curproxy->bind_proc = 0;
7506 }
7507 }
7508
Willy Tarreau3d209582014-05-09 17:06:11 +02007509 /* check and reduce the bind-proc of each listener */
7510 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7511 unsigned long mask;
7512
7513 if (!bind_conf->bind_proc)
7514 continue;
7515
7516 mask = nbits(global.nbproc);
7517 if (curproxy->bind_proc)
7518 mask &= curproxy->bind_proc;
7519 /* mask cannot be null here thanks to the previous checks */
7520
David Carliere6c39412015-07-02 07:00:17 +00007521 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007522 bind_conf->bind_proc &= mask;
7523
7524 if (!bind_conf->bind_proc && nbproc == 1) {
7525 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",
7526 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7527 bind_conf->bind_proc = mask & ~(mask - 1);
7528 }
7529 else if (!bind_conf->bind_proc && nbproc > 1) {
7530 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",
7531 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7532 bind_conf->bind_proc = 0;
7533 }
7534 }
7535
Willy Tarreauff01a212009-03-15 13:46:16 +01007536 switch (curproxy->mode) {
7537 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007538 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007539 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007540 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7541 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007542 cfgerr++;
7543 }
7544
7545 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007546 Warning("config : servers will be ignored for %s '%s'.\n",
7547 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007548 break;
7549
7550 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007551 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007552 break;
7553
7554 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007555 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007556 break;
7557 }
7558
Willy Tarreauf3934b82015-08-11 11:36:45 +02007559 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7560 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7561 proxy_type_str(curproxy), curproxy->id);
7562 err_code |= ERR_WARN;
7563 }
7564
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007565 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007566 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007567 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007568 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7569 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007570 cfgerr++;
7571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007572#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007573 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007574 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7575 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007576 cfgerr++;
7577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007578#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007579 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007580 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7581 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007582 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007583 }
7584 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007585 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007586 /* If no LB algo is set in a backend, and we're not in
7587 * transparent mode, dispatch mode nor proxy mode, we
7588 * want to use balance roundrobin by default.
7589 */
7590 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7591 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007592 }
7593 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007594
Willy Tarreau1620ec32011-08-06 17:05:02 +02007595 if (curproxy->options & PR_O_DISPATCH)
7596 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7597 else if (curproxy->options & PR_O_HTTP_PROXY)
7598 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7599 else if (curproxy->options & PR_O_TRANSP)
7600 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007601
Willy Tarreau1620ec32011-08-06 17:05:02 +02007602 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7603 if (curproxy->options & PR_O_DISABLE404) {
7604 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7605 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7606 err_code |= ERR_WARN;
7607 curproxy->options &= ~PR_O_DISABLE404;
7608 }
7609 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7610 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7611 "send-state", proxy_type_str(curproxy), curproxy->id);
7612 err_code |= ERR_WARN;
7613 curproxy->options &= ~PR_O2_CHK_SNDST;
7614 }
Willy Tarreauef781042010-01-27 11:53:01 +01007615 }
7616
Simon Horman98637e52014-06-20 12:30:16 +09007617 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7618 if (!global.external_check) {
7619 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7620 curproxy->id, "option external-check");
7621 cfgerr++;
7622 }
7623 if (!curproxy->check_command) {
7624 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7625 curproxy->id, "option external-check");
7626 cfgerr++;
7627 }
7628 }
7629
Simon Horman64e34162015-02-06 11:11:57 +09007630 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007631 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7632 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007633 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7634 "'email-alert myhostname', or 'email-alert to' "
7635 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007636 "to be present).\n",
7637 proxy_type_str(curproxy), curproxy->id);
7638 err_code |= ERR_WARN;
7639 free_email_alert(curproxy);
7640 }
7641 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007642 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007643 }
7644
Simon Horman98637e52014-06-20 12:30:16 +09007645 if (curproxy->check_command) {
7646 int clear = 0;
7647 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7648 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7649 "external-check command", proxy_type_str(curproxy), curproxy->id);
7650 err_code |= ERR_WARN;
7651 clear = 1;
7652 }
7653 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007654 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007655 curproxy->id, "external-check command");
7656 cfgerr++;
7657 }
7658 if (clear) {
7659 free(curproxy->check_command);
7660 curproxy->check_command = NULL;
7661 }
7662 }
7663
7664 if (curproxy->check_path) {
7665 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7666 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7667 "external-check path", proxy_type_str(curproxy), curproxy->id);
7668 err_code |= ERR_WARN;
7669 free(curproxy->check_path);
7670 curproxy->check_path = NULL;
7671 }
7672 }
7673
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007674 /* if a default backend was specified, let's find it */
7675 if (curproxy->defbe.name) {
7676 struct proxy *target;
7677
Willy Tarreauafb39922015-05-26 12:04:09 +02007678 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007679 if (!target) {
7680 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7681 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007682 cfgerr++;
7683 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007684 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7685 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007686 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007687 } else if (target->mode != curproxy->mode &&
7688 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7689
7690 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7691 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7692 curproxy->conf.file, curproxy->conf.line,
7693 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7694 target->conf.file, target->conf.line);
7695 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007696 } else {
7697 free(curproxy->defbe.name);
7698 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007699 /* Update tot_fe_maxconn for a further fullconn's computation */
7700 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007701 /* Emit a warning if this proxy also has some servers */
7702 if (curproxy->srv) {
7703 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7704 curproxy->id);
7705 err_code |= ERR_WARN;
7706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007707 }
7708 }
7709
Emeric Brun3f783572017-01-12 11:21:28 +01007710 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7711 /* Case of listen without default backend
7712 * The curproxy will be its own default backend
7713 * so we update tot_fe_maxconn for a further
7714 * fullconn's computation */
7715 curproxy->tot_fe_maxconn += curproxy->maxconn;
7716 }
7717
Willy Tarreau55ea7572007-06-17 19:56:27 +02007718 /* find the target proxy for 'use_backend' rules */
7719 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007720 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007721 struct logformat_node *node;
7722 char *pxname;
7723
7724 /* Try to parse the string as a log format expression. If the result
7725 * of the parsing is only one entry containing a simple string, then
7726 * it's a standard string corresponding to a static rule, thus the
7727 * parsing is cancelled and be.name is restored to be resolved.
7728 */
7729 pxname = rule->be.name;
7730 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007731 curproxy->conf.args.ctx = ARGC_UBK;
7732 curproxy->conf.args.file = rule->file;
7733 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007734 err = NULL;
7735 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7736 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7737 rule->file, rule->line, pxname, err);
7738 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007739 cfgerr++;
7740 continue;
7741 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007742 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7743
7744 if (!LIST_ISEMPTY(&rule->be.expr)) {
7745 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7746 rule->dynamic = 1;
7747 free(pxname);
7748 continue;
7749 }
7750 /* simple string: free the expression and fall back to static rule */
7751 free(node->arg);
7752 free(node);
7753 }
7754
7755 rule->dynamic = 0;
7756 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007757
Willy Tarreauafb39922015-05-26 12:04:09 +02007758 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007759 if (!target) {
7760 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7761 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007762 cfgerr++;
7763 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007764 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7765 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007766 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007767 } else if (target->mode != curproxy->mode &&
7768 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7769
7770 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7771 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7772 curproxy->conf.file, curproxy->conf.line,
7773 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7774 target->conf.file, target->conf.line);
7775 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007776 } else {
7777 free((void *)rule->be.name);
7778 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007779 /* For each target of switching rules, we update
7780 * their tot_fe_maxconn, except if a previous rule point
7781 * on the same backend or on the default backend */
7782 if (rule->be.backend != curproxy->defbe.be) {
7783 struct switching_rule *swrule;
7784
7785 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7786 if (rule == swrule) {
7787 target->tot_fe_maxconn += curproxy->maxconn;
7788 break;
7789 }
7790 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7791 /* there is multiple ref of this backend */
7792 break;
7793 }
7794 }
7795 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007796 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007797 }
7798
Willy Tarreau64ab6072014-09-16 12:17:36 +02007799 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007800 list_for_each_entry(srule, &curproxy->server_rules, list) {
7801 struct server *target = findserver(curproxy, srule->srv.name);
7802
7803 if (!target) {
7804 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7805 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7806 cfgerr++;
7807 continue;
7808 }
7809 free((void *)srule->srv.name);
7810 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007811 }
7812
Emeric Brunb982a3d2010-01-04 15:45:53 +01007813 /* find the target table for 'stick' rules */
7814 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7815 struct proxy *target;
7816
Emeric Brun1d33b292010-01-04 15:47:17 +01007817 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7818 if (mrule->flags & STK_IS_STORE)
7819 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7820
Emeric Brunb982a3d2010-01-04 15:45:53 +01007821 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007822 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007823 else
7824 target = curproxy;
7825
7826 if (!target) {
7827 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7828 curproxy->id, mrule->table.name);
7829 cfgerr++;
7830 }
7831 else if (target->table.size == 0) {
7832 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7833 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7834 cfgerr++;
7835 }
Willy Tarreau12785782012-04-27 21:37:17 +02007836 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7837 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007838 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7839 cfgerr++;
7840 }
7841 else {
7842 free((void *)mrule->table.name);
7843 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007844 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007845 }
7846 }
7847
7848 /* find the target table for 'store response' rules */
7849 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7850 struct proxy *target;
7851
Emeric Brun1d33b292010-01-04 15:47:17 +01007852 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7853
Emeric Brunb982a3d2010-01-04 15:45:53 +01007854 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007855 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007856 else
7857 target = curproxy;
7858
7859 if (!target) {
7860 Alert("Proxy '%s': unable to find store table '%s'.\n",
7861 curproxy->id, mrule->table.name);
7862 cfgerr++;
7863 }
7864 else if (target->table.size == 0) {
7865 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7866 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7867 cfgerr++;
7868 }
Willy Tarreau12785782012-04-27 21:37:17 +02007869 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7870 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007871 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7872 cfgerr++;
7873 }
7874 else {
7875 free((void *)mrule->table.name);
7876 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007877 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007878 }
7879 }
7880
Christopher Faulete4e830d2017-09-18 14:51:41 +02007881 /* check validity for 'tcp-request' layer 4 rules */
7882 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
7883 err = NULL;
7884 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7885 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7886 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01007887 cfgerr++;
7888 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007889 }
7890
Christopher Faulete4e830d2017-09-18 14:51:41 +02007891 /* check validity for 'tcp-request' layer 5 rules */
7892 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
7893 err = NULL;
7894 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7895 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7896 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007897 cfgerr++;
7898 }
7899 }
7900
Christopher Faulete4e830d2017-09-18 14:51:41 +02007901 /* check validity for 'tcp-request' layer 6 rules */
7902 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
7903 err = NULL;
7904 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7905 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7906 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007907 cfgerr++;
7908 }
7909 }
7910
Christopher Faulete4e830d2017-09-18 14:51:41 +02007911 /* check validity for 'http-request' layer 7 rules */
7912 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
7913 err = NULL;
7914 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7915 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7916 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007917 cfgerr++;
7918 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007919 }
7920
Christopher Faulete4e830d2017-09-18 14:51:41 +02007921 /* check validity for 'http-response' layer 7 rules */
7922 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
7923 err = NULL;
7924 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7925 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7926 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02007927 cfgerr++;
7928 }
Willy Tarreau09448f72014-06-25 18:12:15 +02007929 }
7930
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007931 /* move any "block" rules at the beginning of the http-request rules */
7932 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7933 /* insert block_rules into http_req_rules at the beginning */
7934 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7935 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7936 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7937 curproxy->http_req_rules.n = curproxy->block_rules.n;
7938 LIST_INIT(&curproxy->block_rules);
7939 }
7940
Emeric Brun32da3c42010-09-23 18:39:19 +02007941 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007942 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007943
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007944 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02007945 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7946 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007947 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007948 break;
7949 }
7950 }
7951
7952 if (!curpeers) {
7953 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7954 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007955 free((void *)curproxy->table.peers.name);
7956 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007957 cfgerr++;
7958 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007959 else if (curpeers->state == PR_STSTOPPED) {
7960 /* silently disable this peers section */
7961 curproxy->table.peers.p = NULL;
7962 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007963 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007964 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7965 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007966 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007967 cfgerr++;
7968 }
7969 }
7970
Simon Horman9dc49962015-01-30 11:22:59 +09007971
7972 if (curproxy->email_alert.mailers.name) {
7973 struct mailers *curmailers = mailers;
7974
7975 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02007976 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09007977 break;
Simon Horman9dc49962015-01-30 11:22:59 +09007978 }
Simon Horman9dc49962015-01-30 11:22:59 +09007979 if (!curmailers) {
7980 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7981 curproxy->id, curproxy->email_alert.mailers.name);
7982 free_email_alert(curproxy);
7983 cfgerr++;
7984 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02007985 else {
7986 err = NULL;
7987 if (init_email_alert(curmailers, curproxy, &err)) {
7988 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7989 free(err);
7990 cfgerr++;
7991 }
7992 }
Simon Horman9dc49962015-01-30 11:22:59 +09007993 }
7994
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007995 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007996 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007997 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7998 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7999 "proxy", curproxy->id);
8000 cfgerr++;
8001 goto out_uri_auth_compat;
8002 }
8003
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008004 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008005 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008006 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008007 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008008
Willy Tarreau95fa4692010-02-01 13:05:50 +01008009 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8010 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008011
8012 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008013 uri_auth_compat_req[i++] = "realm";
8014 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8015 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008016
Willy Tarreau95fa4692010-02-01 13:05:50 +01008017 uri_auth_compat_req[i++] = "unless";
8018 uri_auth_compat_req[i++] = "{";
8019 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8020 uri_auth_compat_req[i++] = "}";
8021 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008022
Willy Tarreauff011f22011-01-06 17:51:27 +01008023 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8024 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008025 cfgerr++;
8026 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008027 }
8028
Willy Tarreauff011f22011-01-06 17:51:27 +01008029 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008030
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008031 if (curproxy->uri_auth->auth_realm) {
8032 free(curproxy->uri_auth->auth_realm);
8033 curproxy->uri_auth->auth_realm = NULL;
8034 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008035
8036 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008037 }
8038out_uri_auth_compat:
8039
Dragan Dosen43885c72015-10-01 13:18:13 +02008040 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008041 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008042 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8043 if (!curproxy->conf.logformat_sd_string) {
8044 /* set the default logformat_sd_string */
8045 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8046 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008047 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008048 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008049 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008050
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008051 /* compile the log format */
8052 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008053 if (curproxy->conf.logformat_string != default_http_log_format &&
8054 curproxy->conf.logformat_string != default_tcp_log_format &&
8055 curproxy->conf.logformat_string != clf_http_log_format)
8056 free(curproxy->conf.logformat_string);
8057 curproxy->conf.logformat_string = NULL;
8058 free(curproxy->conf.lfs_file);
8059 curproxy->conf.lfs_file = NULL;
8060 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008061
8062 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8063 free(curproxy->conf.logformat_sd_string);
8064 curproxy->conf.logformat_sd_string = NULL;
8065 free(curproxy->conf.lfsd_file);
8066 curproxy->conf.lfsd_file = NULL;
8067 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008068 }
8069
Willy Tarreau62a61232013-04-12 18:13:46 +02008070 if (curproxy->conf.logformat_string) {
8071 curproxy->conf.args.ctx = ARGC_LOG;
8072 curproxy->conf.args.file = curproxy->conf.lfs_file;
8073 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008074 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008075 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008076 SMP_VAL_FE_LOG_END, &err)) {
8077 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8078 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8079 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008080 cfgerr++;
8081 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008082 curproxy->conf.args.file = NULL;
8083 curproxy->conf.args.line = 0;
8084 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008085
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008086 if (curproxy->conf.logformat_sd_string) {
8087 curproxy->conf.args.ctx = ARGC_LOGSD;
8088 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8089 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008090 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008091 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 +01008092 SMP_VAL_FE_LOG_END, &err)) {
8093 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8094 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8095 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008096 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008097 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8098 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8099 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8100 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008101 cfgerr++;
8102 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008103 curproxy->conf.args.file = NULL;
8104 curproxy->conf.args.line = 0;
8105 }
8106
Willy Tarreau62a61232013-04-12 18:13:46 +02008107 if (curproxy->conf.uniqueid_format_string) {
8108 curproxy->conf.args.ctx = ARGC_UIF;
8109 curproxy->conf.args.file = curproxy->conf.uif_file;
8110 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008111 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008112 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 +01008113 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8114 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8115 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8116 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008117 cfgerr++;
8118 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008119 curproxy->conf.args.file = NULL;
8120 curproxy->conf.args.line = 0;
8121 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008122
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008123 /* only now we can check if some args remain unresolved.
8124 * This must be done after the users and groups resolution.
8125 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008126 cfgerr += smp_resolve_args(curproxy);
8127 if (!cfgerr)
8128 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008129
Willy Tarreau2738a142006-07-08 17:28:09 +02008130 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008131 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008132 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008133 (!curproxy->timeout.connect ||
8134 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008135 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008136 " | While not properly invalid, you will certainly encounter various problems\n"
8137 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008138 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008139 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008140 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008141 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008142
Willy Tarreau1fa31262007-12-03 00:36:16 +01008143 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8144 * We must still support older configurations, so let's find out whether those
8145 * parameters have been set or must be copied from contimeouts.
8146 */
8147 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008148 if (!curproxy->timeout.tarpit ||
8149 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008150 /* tarpit timeout not set. We search in the following order:
8151 * default.tarpit, curr.connect, default.connect.
8152 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008153 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008154 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008155 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008156 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008157 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008158 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008159 }
8160 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008161 (!curproxy->timeout.queue ||
8162 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008163 /* queue timeout not set. We search in the following order:
8164 * default.queue, curr.connect, default.connect.
8165 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008166 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008167 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008168 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008169 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008170 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008171 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008172 }
8173 }
8174
Willy Tarreau1620ec32011-08-06 17:05:02 +02008175 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008176 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008177 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008178 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008179 }
8180
Willy Tarreau215663d2014-06-13 18:30:23 +02008181 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8182 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8183 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8184 proxy_type_str(curproxy), curproxy->id);
8185 err_code |= ERR_WARN;
8186 }
8187
Willy Tarreau193b8c62012-11-22 00:17:38 +01008188 /* ensure that cookie capture length is not too large */
8189 if (curproxy->capture_len >= global.tune.cookie_len) {
8190 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8191 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8192 err_code |= ERR_WARN;
8193 curproxy->capture_len = global.tune.cookie_len - 1;
8194 }
8195
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008196 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008197 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008198 curproxy->req_cap_pool = create_pool("ptrcap",
8199 curproxy->nb_req_cap * sizeof(char *),
8200 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008201 }
8202
8203 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008204 curproxy->rsp_cap_pool = create_pool("ptrcap",
8205 curproxy->nb_rsp_cap * sizeof(char *),
8206 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008207 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008208
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008209 switch (curproxy->load_server_state_from_file) {
8210 case PR_SRV_STATE_FILE_UNSPEC:
8211 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8212 break;
8213 case PR_SRV_STATE_FILE_GLOBAL:
8214 if (!global.server_state_file) {
8215 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",
8216 curproxy->id);
8217 err_code |= ERR_WARN;
8218 }
8219 break;
8220 }
8221
Willy Tarreaubaaee002006-06-26 02:48:02 +02008222 /* first, we will invert the servers list order */
8223 newsrv = NULL;
8224 while (curproxy->srv) {
8225 struct server *next;
8226
8227 next = curproxy->srv->next;
8228 curproxy->srv->next = newsrv;
8229 newsrv = curproxy->srv;
8230 if (!next)
8231 break;
8232 curproxy->srv = next;
8233 }
8234
Willy Tarreau17edc812014-01-03 12:14:34 +01008235 /* Check that no server name conflicts. This causes trouble in the stats.
8236 * We only emit a warning for the first conflict affecting each server,
8237 * in order to avoid combinatory explosion if all servers have the same
8238 * name. We do that only for servers which do not have an explicit ID,
8239 * because these IDs were made also for distinguishing them and we don't
8240 * want to annoy people who correctly manage them.
8241 */
8242 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8243 struct server *other_srv;
8244
8245 if (newsrv->puid)
8246 continue;
8247
8248 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8249 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8250 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8251 newsrv->conf.file, newsrv->conf.line,
8252 proxy_type_str(curproxy), curproxy->id,
8253 newsrv->id, other_srv->conf.line);
8254 break;
8255 }
8256 }
8257 }
8258
Willy Tarreaudd701652010-05-25 23:03:02 +02008259 /* assign automatic UIDs to servers which don't have one yet */
8260 next_id = 1;
8261 newsrv = curproxy->srv;
8262 while (newsrv != NULL) {
8263 if (!newsrv->puid) {
8264 /* server ID not set, use automatic numbering with first
8265 * spare entry starting with next_svid.
8266 */
8267 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8268 newsrv->conf.id.key = newsrv->puid = next_id;
8269 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8270 }
8271 next_id++;
8272 newsrv = newsrv->next;
8273 }
8274
Willy Tarreau20697042007-11-15 23:26:18 +01008275 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008276 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008277
Willy Tarreau62c3be22012-01-20 13:12:32 +01008278 /*
8279 * If this server supports a maxconn parameter, it needs a dedicated
8280 * tasks to fill the emptied slots when a connection leaves.
8281 * Also, resolve deferred tracking dependency if needed.
8282 */
8283 newsrv = curproxy->srv;
8284 while (newsrv != NULL) {
8285 if (newsrv->minconn > newsrv->maxconn) {
8286 /* Only 'minconn' was specified, or it was higher than or equal
8287 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8288 * this will avoid further useless expensive computations.
8289 */
8290 newsrv->maxconn = newsrv->minconn;
8291 } else if (newsrv->maxconn && !newsrv->minconn) {
8292 /* minconn was not specified, so we set it to maxconn */
8293 newsrv->minconn = newsrv->maxconn;
8294 }
8295
Willy Tarreau17d45382016-12-22 21:16:08 +01008296 /* this will also properly set the transport layer for prod and checks */
8297 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8298 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8299 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8300 }
Emeric Brun94324a42012-10-11 14:00:19 +02008301
Willy Tarreau2f075e92013-12-03 11:11:34 +01008302 /* set the check type on the server */
8303 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8304
Willy Tarreau62c3be22012-01-20 13:12:32 +01008305 if (newsrv->trackit) {
8306 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008307 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008308 char *pname, *sname;
8309
8310 pname = newsrv->trackit;
8311 sname = strrchr(pname, '/');
8312
8313 if (sname)
8314 *sname++ = '\0';
8315 else {
8316 sname = pname;
8317 pname = NULL;
8318 }
8319
8320 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008321 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008322 if (!px) {
8323 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8324 proxy_type_str(curproxy), curproxy->id,
8325 newsrv->id, pname);
8326 cfgerr++;
8327 goto next_srv;
8328 }
8329 } else
8330 px = curproxy;
8331
8332 srv = findserver(px, sname);
8333 if (!srv) {
8334 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8335 proxy_type_str(curproxy), curproxy->id,
8336 newsrv->id, sname);
8337 cfgerr++;
8338 goto next_srv;
8339 }
8340
Willy Tarreau32091232014-05-16 13:52:00 +02008341 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8342 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8343 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008344 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008345 "tracking as it does not have any check nor agent enabled.\n",
8346 proxy_type_str(curproxy), curproxy->id,
8347 newsrv->id, px->id, srv->id);
8348 cfgerr++;
8349 goto next_srv;
8350 }
8351
8352 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8353
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008354 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008355 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8356 "belongs to a tracking chain looping back to %s/%s.\n",
8357 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008358 newsrv->id, px->id, srv->id, px->id,
8359 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008360 cfgerr++;
8361 goto next_srv;
8362 }
8363
8364 if (curproxy != px &&
8365 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8366 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8367 "tracking: disable-on-404 option inconsistency.\n",
8368 proxy_type_str(curproxy), curproxy->id,
8369 newsrv->id, px->id, srv->id);
8370 cfgerr++;
8371 goto next_srv;
8372 }
8373
Willy Tarreau62c3be22012-01-20 13:12:32 +01008374 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008375 newsrv->tracknext = srv->trackers;
8376 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008377
8378 free(newsrv->trackit);
8379 newsrv->trackit = NULL;
8380 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008381
Willy Tarreau62c3be22012-01-20 13:12:32 +01008382 next_srv:
8383 newsrv = newsrv->next;
8384 }
8385
Olivier Houchard4e694042017-03-14 20:01:29 +01008386 /*
8387 * Try to generate dynamic cookies for servers now.
8388 * It couldn't be done earlier, since at the time we parsed
8389 * the server line, we may not have known yet that we
8390 * should use dynamic cookies, or the secret key may not
8391 * have been provided yet.
8392 */
8393 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8394 newsrv = curproxy->srv;
8395 while (newsrv != NULL) {
8396 srv_set_dyncookie(newsrv);
8397 newsrv = newsrv->next;
8398 }
8399
8400 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008401 /* We have to initialize the server lookup mechanism depending
8402 * on what LB algorithm was choosen.
8403 */
8404
8405 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8406 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8407 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008408 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8409 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8410 init_server_map(curproxy);
8411 } else {
8412 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8413 fwrr_init_server_groups(curproxy);
8414 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008415 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008416
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008417 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008418 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8419 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8420 fwlc_init_server_tree(curproxy);
8421 } else {
8422 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8423 fas_init_server_tree(curproxy);
8424 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008425 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008426
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008427 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008428 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8429 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8430 chash_init_server_tree(curproxy);
8431 } else {
8432 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8433 init_server_map(curproxy);
8434 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008435 break;
8436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008437
8438 if (curproxy->options & PR_O_LOGASAP)
8439 curproxy->to_log &= ~LW_BYTES;
8440
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008441 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008442 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8443 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008444 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8445 proxy_type_str(curproxy), curproxy->id);
8446 err_code |= ERR_WARN;
8447 }
8448
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008449 if (curproxy->mode != PR_MODE_HTTP) {
8450 int optnum;
8451
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008452 if (curproxy->uri_auth) {
8453 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8454 proxy_type_str(curproxy), curproxy->id);
8455 err_code |= ERR_WARN;
8456 curproxy->uri_auth = NULL;
8457 }
8458
Willy Tarreaude7dc882017-03-10 11:49:21 +01008459 if (curproxy->capture_name) {
8460 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8461 proxy_type_str(curproxy), curproxy->id);
8462 err_code |= ERR_WARN;
8463 }
8464
8465 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8466 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8467 proxy_type_str(curproxy), curproxy->id);
8468 err_code |= ERR_WARN;
8469 }
8470
8471 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8472 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8473 proxy_type_str(curproxy), curproxy->id);
8474 err_code |= ERR_WARN;
8475 }
8476
8477 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8478 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8479 proxy_type_str(curproxy), curproxy->id);
8480 err_code |= ERR_WARN;
8481 }
8482
8483 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8484 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8485 proxy_type_str(curproxy), curproxy->id);
8486 err_code |= ERR_WARN;
8487 }
8488
Willy Tarreau87cf5142011-08-19 22:57:24 +02008489 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008490 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8491 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8492 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008493 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008494 }
8495
8496 if (curproxy->options & PR_O_ORGTO) {
8497 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8498 "originalto", proxy_type_str(curproxy), curproxy->id);
8499 err_code |= ERR_WARN;
8500 curproxy->options &= ~PR_O_ORGTO;
8501 }
8502
8503 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8504 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8505 (curproxy->cap & cfg_opts[optnum].cap) &&
8506 (curproxy->options & cfg_opts[optnum].val)) {
8507 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8508 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8509 err_code |= ERR_WARN;
8510 curproxy->options &= ~cfg_opts[optnum].val;
8511 }
8512 }
8513
8514 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8515 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8516 (curproxy->cap & cfg_opts2[optnum].cap) &&
8517 (curproxy->options2 & cfg_opts2[optnum].val)) {
8518 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8519 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8520 err_code |= ERR_WARN;
8521 curproxy->options2 &= ~cfg_opts2[optnum].val;
8522 }
8523 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008524
Willy Tarreau29fbe512015-08-20 19:35:14 +02008525#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008526 if (curproxy->conn_src.bind_hdr_occ) {
8527 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008528 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008529 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008530 err_code |= ERR_WARN;
8531 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008532#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008533 }
8534
Willy Tarreaubaaee002006-06-26 02:48:02 +02008535 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008536 * ensure that we're not cross-dressing a TCP server into HTTP.
8537 */
8538 newsrv = curproxy->srv;
8539 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008540 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008541 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8542 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008543 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008544 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008545
Willy Tarreau0cec3312011-10-31 13:49:26 +01008546 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8547 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8548 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8549 err_code |= ERR_WARN;
8550 }
8551
Willy Tarreauc93cd162014-05-13 15:54:22 +02008552 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008553 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8554 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8555 err_code |= ERR_WARN;
8556 }
8557
Willy Tarreau29fbe512015-08-20 19:35:14 +02008558#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008559 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8560 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008561 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 +01008562 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008563 err_code |= ERR_WARN;
8564 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008565#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008566
8567 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8568 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8569 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8570 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8571 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8572 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",
8573 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8574 err_code |= ERR_WARN;
8575 }
8576
8577
8578 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8579 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",
8580 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8581 err_code |= ERR_WARN;
8582 }
8583 }
8584
Willy Tarreau21d2af32008-02-14 20:25:24 +01008585 newsrv = newsrv->next;
8586 }
8587
Willy Tarreaue42bd962014-09-16 16:21:19 +02008588 /* check if we have a frontend with "tcp-request content" looking at L7
8589 * with no inspect-delay
8590 */
8591 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008592 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8593 if (arule->action == ACT_TCP_CAPTURE &&
8594 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008595 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008596 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8597 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008598 break;
8599 }
8600
Christopher Faulete4e830d2017-09-18 14:51:41 +02008601 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008602 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8603 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8604 " This means that these rules will randomly find their contents. This can be fixed by"
8605 " setting the tcp-request inspect-delay.\n",
8606 proxy_type_str(curproxy), curproxy->id);
8607 err_code |= ERR_WARN;
8608 }
8609 }
8610
Christopher Fauletd7c91962015-04-30 11:48:27 +02008611 /* Check filter configuration, if any */
8612 cfgerr += flt_check(curproxy);
8613
Willy Tarreauc1a21672009-08-16 22:37:44 +02008614 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008615 if (!curproxy->accept)
8616 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008617
Willy Tarreauc1a21672009-08-16 22:37:44 +02008618 if (curproxy->tcp_req.inspect_delay ||
8619 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008620 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008621
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008622 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008623 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008624 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008625 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008626
8627 /* both TCP and HTTP must check switching rules */
8628 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008629
8630 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008631 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008632 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8633 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 +01008634 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008635 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8636 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008637 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008638 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008639 }
8640
8641 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008642 if (curproxy->tcp_req.inspect_delay ||
8643 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8644 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8645
Emeric Brun97679e72010-09-23 17:56:44 +02008646 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8647 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8648
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008649 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008650 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008651 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008652 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008653
8654 /* If the backend does requires RDP cookie persistence, we have to
8655 * enable the corresponding analyser.
8656 */
8657 if (curproxy->options2 & PR_O2_RDPC_PRST)
8658 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008659
8660 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008661 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008662 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8663 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 +01008664 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008665 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8666 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008667 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008668 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008669 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008670 }
8671
8672 /***********************************************************/
8673 /* At this point, target names have already been resolved. */
8674 /***********************************************************/
8675
8676 /* Check multi-process mode compatibility */
8677
8678 if (global.nbproc > 1 && global.stats_fe) {
8679 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8680 unsigned long mask;
8681
8682 mask = nbits(global.nbproc);
8683 if (global.stats_fe->bind_proc)
8684 mask &= global.stats_fe->bind_proc;
8685
8686 if (bind_conf->bind_proc)
8687 mask &= bind_conf->bind_proc;
8688
8689 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008690 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008691 break;
8692 }
8693 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8694 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");
8695 }
8696 }
8697
8698 /* Make each frontend inherit bind-process from its listeners when not specified. */
8699 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8700 if (curproxy->bind_proc)
8701 continue;
8702
8703 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8704 unsigned long mask;
8705
Willy Tarreaue428b082015-05-04 21:57:58 +02008706 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008707 curproxy->bind_proc |= mask;
8708 }
8709
8710 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008711 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008712 }
8713
8714 if (global.stats_fe) {
8715 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8716 unsigned long mask;
8717
Cyril Bonté06181952016-02-24 00:14:54 +01008718 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008719 global.stats_fe->bind_proc |= mask;
8720 }
8721 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008722 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008723 }
8724
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008725 /* propagate bindings from frontends to backends. Don't do it if there
8726 * are any fatal errors as we must not call it with unresolved proxies.
8727 */
8728 if (!cfgerr) {
8729 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8730 if (curproxy->cap & PR_CAP_FE)
8731 propagate_processes(curproxy, NULL);
8732 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008733 }
8734
8735 /* Bind each unbound backend to all processes when not specified. */
8736 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8737 if (curproxy->bind_proc)
8738 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008739 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008740 }
8741
8742 /*******************************************************/
8743 /* At this step, all proxies have a non-null bind_proc */
8744 /*******************************************************/
8745
8746 /* perform the final checks before creating tasks */
8747
8748 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8749 struct listener *listener;
8750 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008751
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008752 /* Configure SSL for each bind line.
8753 * Note: if configuration fails at some point, the ->ctx member
8754 * remains NULL so that listeners can later detach.
8755 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008756 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008757 if (bind_conf->xprt->prepare_bind_conf &&
8758 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008759 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008760 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008761
Willy Tarreaue6b98942007-10-29 01:09:36 +01008762 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008763 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008764 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008765 int nbproc;
8766
8767 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008768 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008769 nbits(global.nbproc));
8770
8771 if (!nbproc) /* no intersection between listener and frontend */
8772 nbproc = 1;
8773
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008774 if (!listener->luid) {
8775 /* listener ID not set, use automatic numbering with first
8776 * spare entry starting with next_luid.
8777 */
8778 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8779 listener->conf.id.key = listener->luid = next_id;
8780 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008781 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008782 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008783
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008784 /* enable separate counters */
8785 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008786 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008787 if (!listener->name)
8788 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008789 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008790
Willy Tarreaue6b98942007-10-29 01:09:36 +01008791 if (curproxy->options & PR_O_TCP_NOLING)
8792 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008793 if (!listener->maxconn)
8794 listener->maxconn = curproxy->maxconn;
8795 if (!listener->backlog)
8796 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008797 if (!listener->maxaccept)
8798 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8799
8800 /* we want to have an optimal behaviour on single process mode to
8801 * maximize the work at once, but in multi-process we want to keep
8802 * some fairness between processes, so we target half of the max
8803 * number of events to be balanced over all the processes the proxy
8804 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8805 * used to disable the limit.
8806 */
8807 if (listener->maxaccept > 0) {
8808 if (nbproc > 1)
8809 listener->maxaccept = (listener->maxaccept + 1) / 2;
8810 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8811 }
8812
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008813 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008814 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008815 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008816
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008817 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008818 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008819
Willy Tarreau620408f2016-10-21 16:37:51 +02008820 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8821 listener->options |= LI_O_TCP_L5_RULES;
8822
Willy Tarreaude3041d2010-05-31 10:56:17 +02008823 if (curproxy->mon_mask.s_addr)
8824 listener->options |= LI_O_CHK_MONNET;
8825
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008826 /* smart accept mode is automatic in HTTP mode */
8827 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008828 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008829 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8830 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008831 }
8832
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008833 /* Release unused SSL configs */
8834 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008835 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8836 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008837 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008838
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008839 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008840 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008841 int count, maxproc = 0;
8842
8843 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008844 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008845 if (count > maxproc)
8846 maxproc = count;
8847 }
8848 /* backends have 0, frontends have 1 or more */
8849 if (maxproc != 1)
8850 Warning("Proxy '%s': in multi-process mode, stats will be"
8851 " limited to process assigned to the current request.\n",
8852 curproxy->id);
8853
Willy Tarreau102df612014-05-07 23:56:38 +02008854 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8855 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8856 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008857 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008858 }
Willy Tarreau102df612014-05-07 23:56:38 +02008859 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8860 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8861 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008862 }
8863 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008864
8865 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02008866 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02008867 if (curproxy->task) {
8868 curproxy->task->context = curproxy;
8869 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02008870 } else {
8871 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8872 curproxy->id);
8873 cfgerr++;
8874 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008875 }
8876
Willy Tarreaufbb78422011-06-05 15:38:35 +02008877 /* automatically compute fullconn if not set. We must not do it in the
8878 * loop above because cross-references are not yet fully resolved.
8879 */
8880 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8881 /* If <fullconn> is not set, let's set it to 10% of the sum of
8882 * the possible incoming frontend's maxconns.
8883 */
8884 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008885 /* we have the sum of the maxconns in <total>. We only
8886 * keep 10% of that sum to set the default fullconn, with
8887 * a hard minimum of 1 (to avoid a divide by zero).
8888 */
Emeric Brun3f783572017-01-12 11:21:28 +01008889 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008890 if (!curproxy->fullconn)
8891 curproxy->fullconn = 1;
8892 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008893 }
8894
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008895 /*
8896 * Recount currently required checks.
8897 */
8898
8899 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8900 int optnum;
8901
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008902 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8903 if (curproxy->options & cfg_opts[optnum].val)
8904 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008905
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008906 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8907 if (curproxy->options2 & cfg_opts2[optnum].val)
8908 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008909 }
8910
Willy Tarreau0fca4832015-05-01 19:12:05 +02008911 /* compute the required process bindings for the peers */
8912 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8913 if (curproxy->table.peers.p)
8914 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8915
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008916 if (cfg_peers) {
8917 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02008918 struct peer *p, *pb;
8919
Willy Tarreau1e273012015-05-01 19:15:17 +02008920 /* Remove all peers sections which don't have a valid listener,
8921 * which are not used by any table, or which are bound to more
8922 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008923 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008924 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02008925 while (*last) {
8926 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008927
8928 if (curpeers->state == PR_STSTOPPED) {
8929 /* the "disabled" keyword was present */
8930 if (curpeers->peers_fe)
8931 stop_proxy(curpeers->peers_fe);
8932 curpeers->peers_fe = NULL;
8933 }
8934 else if (!curpeers->peers_fe) {
8935 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8936 curpeers->id, localpeer);
8937 }
David Carliere6c39412015-07-02 07:00:17 +00008938 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008939 /* either it's totally stopped or too much used */
8940 if (curpeers->peers_fe->bind_proc) {
8941 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008942 "running in different processes (%d different ones). "
8943 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008944 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008945 cfgerr++;
8946 }
8947 stop_proxy(curpeers->peers_fe);
8948 curpeers->peers_fe = NULL;
8949 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008950 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008951 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008952 last = &curpeers->next;
8953 continue;
8954 }
8955
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008956 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008957 p = curpeers->remote;
8958 while (p) {
8959 pb = p->next;
8960 free(p->id);
8961 free(p);
8962 p = pb;
8963 }
8964
8965 /* Destroy and unlink this curpeers section.
8966 * Note: curpeers is backed up into *last.
8967 */
8968 free(curpeers->id);
8969 curpeers = curpeers->next;
8970 free(*last);
8971 *last = curpeers;
8972 }
8973 }
8974
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008975 /* initialize stick-tables on backend capable proxies. This must not
8976 * be done earlier because the data size may be discovered while parsing
8977 * other proxies.
8978 */
8979 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8980 if (curproxy->state == PR_STSTOPPED)
8981 continue;
8982
8983 if (!stktable_init(&curproxy->table)) {
8984 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8985 cfgerr++;
8986 }
8987 }
8988
Simon Horman0d16a402015-01-30 11:22:58 +09008989 if (mailers) {
8990 struct mailers *curmailers = mailers, **last;
8991 struct mailer *m, *mb;
8992
8993 /* Remove all mailers sections which don't have a valid listener.
8994 * This can happen when a mailers section is never referenced.
8995 */
8996 last = &mailers;
8997 while (*last) {
8998 curmailers = *last;
8999 if (curmailers->users) {
9000 last = &curmailers->next;
9001 continue;
9002 }
9003
9004 Warning("Removing incomplete section 'mailers %s'.\n",
9005 curmailers->id);
9006
9007 m = curmailers->mailer_list;
9008 while (m) {
9009 mb = m->next;
9010 free(m->id);
9011 free(m);
9012 m = mb;
9013 }
9014
9015 /* Destroy and unlink this curmailers section.
9016 * Note: curmailers is backed up into *last.
9017 */
9018 free(curmailers->id);
9019 curmailers = curmailers->next;
9020 free(*last);
9021 *last = curmailers;
9022 }
9023 }
9024
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009025 /* Update server_state_file_name to backend name if backend is supposed to use
9026 * a server-state file locally defined and none has been provided */
9027 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9028 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9029 curproxy->server_state_file_name == NULL)
9030 curproxy->server_state_file_name = strdup(curproxy->id);
9031 }
9032
Willy Tarreau34eb6712011-10-24 18:15:04 +02009033 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009034 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009035 MEM_F_SHARED);
9036
William Lallemand48b4bb42017-10-23 14:36:34 +02009037 list_for_each_entry(postparser, &postparsers, list) {
9038 if (postparser->func)
9039 cfgerr += postparser->func();
9040 }
9041
Willy Tarreaubb925012009-07-23 13:36:36 +02009042 if (cfgerr > 0)
9043 err_code |= ERR_ALERT | ERR_FATAL;
9044 out:
9045 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009046}
9047
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009048/*
9049 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9050 * parsing sessions.
9051 */
9052void cfg_register_keywords(struct cfg_kw_list *kwl)
9053{
9054 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9055}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009056
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009057/*
9058 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9059 */
9060void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9061{
9062 LIST_DEL(&kwl->list);
9063 LIST_INIT(&kwl->list);
9064}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009065
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009066/* this function register new section in the haproxy configuration file.
9067 * <section_name> is the name of this new section and <section_parser>
9068 * is the called parser. If two section declaration have the same name,
9069 * only the first declared is used.
9070 */
9071int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009072 int (*section_parser)(const char *, int, char **, int),
9073 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009074{
9075 struct cfg_section *cs;
9076
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009077 list_for_each_entry(cs, &sections, list) {
9078 if (strcmp(cs->section_name, section_name) == 0) {
9079 Alert("register section '%s': already registered.\n", section_name);
9080 return 0;
9081 }
9082 }
9083
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009084 cs = calloc(1, sizeof(*cs));
9085 if (!cs) {
9086 Alert("register section '%s': out of memory.\n", section_name);
9087 return 0;
9088 }
9089
9090 cs->section_name = section_name;
9091 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009092 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009093
9094 LIST_ADDQ(&sections, &cs->list);
9095
9096 return 1;
9097}
9098
William Lallemand48b4bb42017-10-23 14:36:34 +02009099/* this function register a new function which will be called once the haproxy
9100 * configuration file has been parsed. It's useful to check dependencies
9101 * between sections or to resolve items once everything is parsed.
9102 */
9103int cfg_register_postparser(char *name, int (*func)())
9104{
9105 struct cfg_postparser *cp;
9106
9107 cp = calloc(1, sizeof(*cp));
9108 if (!cp) {
9109 Alert("register postparser '%s': out of memory.\n", name);
9110 return 0;
9111 }
9112 cp->name = name;
9113 cp->func = func;
9114
9115 LIST_ADDQ(&postparsers, &cp->list);
9116
9117 return 1;
9118}
9119
Willy Tarreaubaaee002006-06-26 02:48:02 +02009120/*
David Carlier845efb52015-09-25 11:49:18 +01009121 * free all config section entries
9122 */
9123void cfg_unregister_sections(void)
9124{
9125 struct cfg_section *cs, *ics;
9126
9127 list_for_each_entry_safe(cs, ics, &sections, list) {
9128 LIST_DEL(&cs->list);
9129 free(cs);
9130 }
9131}
9132
Christopher Faulet7110b402016-10-26 11:09:44 +02009133void cfg_backup_sections(struct list *backup_sections)
9134{
9135 struct cfg_section *cs, *ics;
9136
9137 list_for_each_entry_safe(cs, ics, &sections, list) {
9138 LIST_DEL(&cs->list);
9139 LIST_ADDQ(backup_sections, &cs->list);
9140 }
9141}
9142
9143void cfg_restore_sections(struct list *backup_sections)
9144{
9145 struct cfg_section *cs, *ics;
9146
9147 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9148 LIST_DEL(&cs->list);
9149 LIST_ADDQ(&sections, &cs->list);
9150 }
9151}
9152
Willy Tarreau659fbf02016-05-26 17:55:28 +02009153__attribute__((constructor))
9154static void cfgparse_init(void)
9155{
9156 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009157 cfg_register_section("listen", cfg_parse_listen, NULL);
9158 cfg_register_section("frontend", cfg_parse_listen, NULL);
9159 cfg_register_section("backend", cfg_parse_listen, NULL);
9160 cfg_register_section("defaults", cfg_parse_listen, NULL);
9161 cfg_register_section("global", cfg_parse_global, NULL);
9162 cfg_register_section("userlist", cfg_parse_users, NULL);
9163 cfg_register_section("peers", cfg_parse_peers, NULL);
9164 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9165 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9166 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009167}
9168
David Carlier845efb52015-09-25 11:49:18 +01009169/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009170 * Local variables:
9171 * c-indent-level: 8
9172 * c-basic-offset: 8
9173 * End:
9174 */