blob: ca2d5d79dbdf8b506d02e258583fb9525a7ce8f8 [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;
Emeric Brun80527f52017-06-19 17:46:37 +02002042 SPIN_INIT(&newpeer->lock);
Willy Tarreau26d8c592012-05-07 18:12:14 +02002043
Emeric Brun32da3c42010-09-23 18:39:19 +02002044 if (strcmp(newpeer->id, localpeer) == 0) {
2045 /* Current is local peer, it define a frontend */
2046 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002047 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002048
2049 if (!curpeers->peers_fe) {
2050 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2051 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2052 err_code |= ERR_ALERT | ERR_ABORT;
2053 goto out;
2054 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002055
Willy Tarreau237250c2011-07-29 01:49:03 +02002056 init_new_proxy(curpeers->peers_fe);
2057 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002058 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002059 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2060 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002061 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002062
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002063 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002064
Willy Tarreau902636f2013-03-10 19:44:48 +01002065 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2066 if (errmsg && *errmsg) {
2067 indent_msg(&errmsg, 2);
2068 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002069 }
2070 else
2071 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2072 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002073 err_code |= ERR_FATAL;
2074 goto out;
2075 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002076
2077 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002078 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002079 l->maxconn = curpeers->peers_fe->maxconn;
2080 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002081 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002082 l->analysers |= curpeers->peers_fe->fe_req_ana;
2083 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002084 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2085 global.maxsock += l->maxconn;
2086 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002087 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002088 else {
2089 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2090 file, linenum, args[0], args[1],
2091 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2092 err_code |= ERR_FATAL;
2093 goto out;
2094 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002095 }
2096 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002097 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2098 curpeers->state = PR_STSTOPPED;
2099 }
2100 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2101 curpeers->state = PR_STNEW;
2102 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002103 else if (*args[0] != 0) {
2104 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
2107 }
2108
2109out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002110 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002111 return err_code;
2112}
2113
Baptiste Assmann325137d2015-04-13 23:40:55 +02002114/*
2115 * Parse a <resolvers> section.
2116 * Returns the error code, 0 if OK, or any combination of :
2117 * - ERR_ABORT: must abort ASAP
2118 * - ERR_FATAL: we can continue parsing but not start the service
2119 * - ERR_WARN: a warning has been emitted
2120 * - ERR_ALERT: an alert has been emitted
2121 * Only the two first ones can stop processing, the two others are just
2122 * indicators.
2123 */
2124int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2125{
2126 static struct dns_resolvers *curr_resolvers = NULL;
2127 struct dns_nameserver *newnameserver = NULL;
2128 const char *err;
2129 int err_code = 0;
2130 char *errmsg = NULL;
2131
2132 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2133 if (!*args[1]) {
2134 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2135 err_code |= ERR_ALERT | ERR_ABORT;
2136 goto out;
2137 }
2138
2139 err = invalid_char(args[1]);
2140 if (err) {
2141 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2142 file, linenum, *err, args[0], args[1]);
2143 err_code |= ERR_ALERT | ERR_ABORT;
2144 goto out;
2145 }
2146
2147 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2148 /* Error if two resolvers owns the same name */
2149 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2150 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2151 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2152 err_code |= ERR_ALERT | ERR_ABORT;
2153 }
2154 }
2155
Vincent Bernat02779b62016-04-03 13:48:43 +02002156 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002157 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2158 err_code |= ERR_ALERT | ERR_ABORT;
2159 goto out;
2160 }
2161
2162 /* default values */
2163 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2164 curr_resolvers->conf.file = strdup(file);
2165 curr_resolvers->conf.line = linenum;
2166 curr_resolvers->id = strdup(args[1]);
2167 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002168 /* default maximum response size */
2169 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002170 /* default hold period for nx, other, refuse and timeout is 30s */
2171 curr_resolvers->hold.nx = 30000;
2172 curr_resolvers->hold.other = 30000;
2173 curr_resolvers->hold.refused = 30000;
2174 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002175 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002177 curr_resolvers->hold.valid = 10000;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002178 curr_resolvers->timeout.resolve = 1000;
2179 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002180 curr_resolvers->resolve_retries = 3;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002181 curr_resolvers->nb_nameservers = 0;
2182 LIST_INIT(&curr_resolvers->nameservers);
2183 LIST_INIT(&curr_resolvers->resolutions.curr);
2184 LIST_INIT(&curr_resolvers->resolutions.wait);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002185 }
2186 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2187 struct sockaddr_storage *sk;
2188 int port1, port2;
2189 struct protocol *proto;
2190
2191 if (!*args[2]) {
2192 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2193 file, linenum, args[0]);
2194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
2196 }
2197
2198 err = invalid_char(args[1]);
2199 if (err) {
2200 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2201 file, linenum, *err, args[1]);
2202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
2204 }
2205
Christopher Faulet67957bd2017-09-27 11:00:59 +02002206 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002207 /* Error if two resolvers owns the same name */
2208 if (strcmp(newnameserver->id, args[1]) == 0) {
2209 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2210 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2211 err_code |= ERR_ALERT | ERR_FATAL;
2212 }
2213 }
2214
Vincent Bernat02779b62016-04-03 13:48:43 +02002215 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002216 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2217 err_code |= ERR_ALERT | ERR_ABORT;
2218 goto out;
2219 }
2220
2221 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002222 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002223 newnameserver->resolvers = curr_resolvers;
2224 newnameserver->conf.file = strdup(file);
2225 newnameserver->conf.line = linenum;
2226 newnameserver->id = strdup(args[1]);
2227
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002228 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002229 if (!sk) {
2230 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
2233 }
2234
2235 proto = protocol_by_family(sk->ss_family);
2236 if (!proto || !proto->connect) {
2237 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2238 file, linenum, args[0], args[1]);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242
2243 if (port1 != port2) {
2244 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2245 file, linenum, args[0], args[1], args[2]);
2246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
2248 }
2249
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002250 if (!port1 && !port2) {
2251 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2252 file, linenum, args[0], args[1]);
2253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
2255 }
2256
Baptiste Assmann325137d2015-04-13 23:40:55 +02002257 newnameserver->addr = *sk;
2258 }
2259 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2260 const char *res;
2261 unsigned int time;
2262
2263 if (!*args[2]) {
2264 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2265 file, linenum, args[0]);
2266 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2271 if (res) {
2272 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2273 file, linenum, *res, args[0]);
2274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
2276 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002277 if (strcmp(args[1], "nx") == 0)
2278 curr_resolvers->hold.nx = time;
2279 else if (strcmp(args[1], "other") == 0)
2280 curr_resolvers->hold.other = time;
2281 else if (strcmp(args[1], "refused") == 0)
2282 curr_resolvers->hold.refused = time;
2283 else if (strcmp(args[1], "timeout") == 0)
2284 curr_resolvers->hold.timeout = time;
2285 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002286 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002287 else if (strcmp(args[1], "obsolete") == 0)
2288 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002289 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002290 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002291 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
2294 }
2295
2296 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002297 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002298 int i = 0;
2299
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002300 if (!*args[1]) {
2301 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2302 file, linenum, args[0]);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002306
2307 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002308 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2309 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2310 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
2313 }
2314
2315 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002316 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002317 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002318 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2319 file, linenum, args[0]);
2320 err_code |= ERR_WARN;
2321 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002322 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002323 else if (strcmp(args[0], "resolve_retries") == 0) {
2324 if (!*args[1]) {
2325 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2326 file, linenum, args[0]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
2330 curr_resolvers->resolve_retries = atoi(args[1]);
2331 }
2332 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002333 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002334 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002335 file, linenum, args[0]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002339 else if (strcmp(args[1], "retry") == 0 ||
2340 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002341 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002342 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002343
2344 if (!*args[2]) {
2345 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2346 file, linenum, args[0], args[1]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002350 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002351 if (res) {
2352 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2353 file, linenum, *res, args[0], args[1]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002357 if (args[1][2] == 't')
2358 curr_resolvers->timeout.retry = tout;
2359 else
2360 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002361 }
2362 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002363 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002364 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
2367 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002368 } /* neither "nameserver" nor "resolvers" */
2369 else if (*args[0] != 0) {
2370 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
2373 }
2374
2375 out:
2376 free(errmsg);
2377 return err_code;
2378}
Simon Horman0d16a402015-01-30 11:22:58 +09002379
2380/*
William Lallemand51097192015-04-14 16:35:22 +02002381 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002382 * Returns the error code, 0 if OK, or any combination of :
2383 * - ERR_ABORT: must abort ASAP
2384 * - ERR_FATAL: we can continue parsing but not start the service
2385 * - ERR_WARN: a warning has been emitted
2386 * - ERR_ALERT: an alert has been emitted
2387 * Only the two first ones can stop processing, the two others are just
2388 * indicators.
2389 */
2390int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2391{
2392 static struct mailers *curmailers = NULL;
2393 struct mailer *newmailer = NULL;
2394 const char *err;
2395 int err_code = 0;
2396 char *errmsg = NULL;
2397
2398 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2399 if (!*args[1]) {
2400 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2401 err_code |= ERR_ALERT | ERR_ABORT;
2402 goto out;
2403 }
2404
2405 err = invalid_char(args[1]);
2406 if (err) {
2407 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2408 file, linenum, *err, args[0], args[1]);
2409 err_code |= ERR_ALERT | ERR_ABORT;
2410 goto out;
2411 }
2412
2413 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2414 /*
2415 * If there are two proxies with the same name only following
2416 * combinations are allowed:
2417 */
2418 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002419 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 +09002420 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002421 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002422 }
2423 }
2424
Vincent Bernat02779b62016-04-03 13:48:43 +02002425 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002426 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2427 err_code |= ERR_ALERT | ERR_ABORT;
2428 goto out;
2429 }
2430
2431 curmailers->next = mailers;
2432 mailers = curmailers;
2433 curmailers->conf.file = strdup(file);
2434 curmailers->conf.line = linenum;
2435 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002436 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2437 * But need enough time so that timeouts don't occur
2438 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002439 }
2440 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2441 struct sockaddr_storage *sk;
2442 int port1, port2;
2443 struct protocol *proto;
2444
2445 if (!*args[2]) {
2446 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2447 file, linenum, args[0]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451
2452 err = invalid_char(args[1]);
2453 if (err) {
2454 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2455 file, linenum, *err, args[1]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459
Vincent Bernat02779b62016-04-03 13:48:43 +02002460 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002461 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2462 err_code |= ERR_ALERT | ERR_ABORT;
2463 goto out;
2464 }
2465
2466 /* the mailers are linked backwards first */
2467 curmailers->count++;
2468 newmailer->next = curmailers->mailer_list;
2469 curmailers->mailer_list = newmailer;
2470 newmailer->mailers = curmailers;
2471 newmailer->conf.file = strdup(file);
2472 newmailer->conf.line = linenum;
2473
2474 newmailer->id = strdup(args[1]);
2475
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002476 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002477 if (!sk) {
2478 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
2481 }
2482
2483 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002484 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2485 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002486 file, linenum, args[0], args[1]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490
2491 if (port1 != port2) {
2492 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2493 file, linenum, args[0], args[1], args[2]);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497
2498 if (!port1) {
2499 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2500 file, linenum, args[0], args[1], args[2]);
2501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
2504
2505 newmailer->addr = *sk;
2506 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002507 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002508 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002509 }
2510 else if (strcmp(args[0], "timeout") == 0) {
2511 if (!*args[1]) {
2512 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2513 file, linenum, args[0]);
2514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
2516 }
2517 else if (strcmp(args[1], "mail") == 0) {
2518 const char *res;
2519 unsigned int timeout_mail;
2520 if (!*args[2]) {
2521 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2522 file, linenum, args[0], args[1]);
2523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
2525 }
2526 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2527 if (res) {
2528 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2529 file, linenum, *res, args[0]);
2530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
2532 }
2533 if (timeout_mail <= 0) {
2534 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
2537 }
2538 curmailers->timeout.mail = timeout_mail;
2539 } else {
2540 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2541 file, linenum, args[0], args[1]);
2542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
2544 }
2545 }
Simon Horman0d16a402015-01-30 11:22:58 +09002546 else if (*args[0] != 0) {
2547 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
2550 }
2551
2552out:
2553 free(errmsg);
2554 return err_code;
2555}
2556
Simon Horman9dc49962015-01-30 11:22:59 +09002557static void free_email_alert(struct proxy *p)
2558{
2559 free(p->email_alert.mailers.name);
2560 p->email_alert.mailers.name = NULL;
2561 free(p->email_alert.from);
2562 p->email_alert.from = NULL;
2563 free(p->email_alert.to);
2564 p->email_alert.to = NULL;
2565 free(p->email_alert.myhostname);
2566 p->email_alert.myhostname = NULL;
2567}
2568
Willy Tarreau3842f002009-06-14 11:39:52 +02002569int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570{
2571 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002572 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002573 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002574 int rc;
2575 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002576 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002577 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002578 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002579 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002580 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581
Willy Tarreau977b8e42006-12-29 14:19:17 +01002582 if (!strcmp(args[0], "listen"))
2583 rc = PR_CAP_LISTEN;
2584 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002585 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002586 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002587 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002588 else
2589 rc = PR_CAP_NONE;
2590
2591 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 if (!*args[1]) {
2593 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002594 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_ABORT;
2597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002599
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002600 err = invalid_char(args[1]);
2601 if (err) {
2602 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2603 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002605 }
2606
Willy Tarreau8f50b682015-05-26 11:45:02 +02002607 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2608 if (curproxy) {
2609 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2610 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2611 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002613 }
2614
Vincent Bernat02779b62016-04-03 13:48:43 +02002615 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_ABORT;
2618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002620
Willy Tarreau97cb7802010-01-03 20:23:58 +01002621 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 curproxy->next = proxy;
2623 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002624 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2625 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002626 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002628 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002629 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630
William Lallemand6e62fb62015-04-28 16:55:23 +02002631 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2632 if (curproxy->cap & PR_CAP_FE)
2633 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 }
2636
2637 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002638 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002639 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002640
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002643 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002644 curproxy->no_options = defproxy.no_options;
2645 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002646 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002647 curproxy->except_net = defproxy.except_net;
2648 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002649 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002650 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002652 if (defproxy.fwdfor_hdr_len) {
2653 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2654 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2655 }
2656
Willy Tarreaub86db342009-11-30 11:50:16 +01002657 if (defproxy.orgto_hdr_len) {
2658 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2659 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2660 }
2661
Mark Lamourinec2247f02012-01-04 13:02:01 -05002662 if (defproxy.server_id_hdr_len) {
2663 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2664 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2665 }
2666
Willy Tarreau977b8e42006-12-29 14:19:17 +01002667 if (curproxy->cap & PR_CAP_FE) {
2668 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002669 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002670 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671
2672 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002673 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2674 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002675
2676 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002680 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002681 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002682 curproxy->fullconn = defproxy.fullconn;
2683 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002684 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002685 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002687 if (defproxy.check_req) {
2688 curproxy->check_req = calloc(1, defproxy.check_len);
2689 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2690 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002691 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002693 if (defproxy.expect_str) {
2694 curproxy->expect_str = strdup(defproxy.expect_str);
2695 if (defproxy.expect_regex) {
2696 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002697 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2698 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002699 }
2700 }
2701
Willy Tarreau67402132012-05-31 20:40:20 +02002702 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002703 if (defproxy.cookie_name)
2704 curproxy->cookie_name = strdup(defproxy.cookie_name);
2705 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002706
2707 if (defproxy.dyncookie_key)
2708 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002709 if (defproxy.cookie_domain)
2710 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002711
Willy Tarreau31936852010-10-06 16:59:56 +02002712 if (defproxy.cookie_maxidle)
2713 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2714
2715 if (defproxy.cookie_maxlife)
2716 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2717
Emeric Brun647caf12009-06-30 17:57:00 +02002718 if (defproxy.rdp_cookie_name)
2719 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2720 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2721
Willy Tarreau01732802007-11-01 22:48:15 +01002722 if (defproxy.url_param_name)
2723 curproxy->url_param_name = strdup(defproxy.url_param_name);
2724 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002725
Benoitaffb4812009-03-25 13:02:10 +01002726 if (defproxy.hh_name)
2727 curproxy->hh_name = strdup(defproxy.hh_name);
2728 curproxy->hh_len = defproxy.hh_len;
2729 curproxy->hh_match_domain = defproxy.hh_match_domain;
2730
Willy Tarreauef9a3602012-12-08 22:29:20 +01002731 if (defproxy.conn_src.iface_name)
2732 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2733 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002734 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002735#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002736 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002737#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002738 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002741 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002742 if (defproxy.capture_name)
2743 curproxy->capture_name = strdup(defproxy.capture_name);
2744 curproxy->capture_namelen = defproxy.capture_namelen;
2745 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747
Willy Tarreau977b8e42006-12-29 14:19:17 +01002748 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002749 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002750 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002751 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002752 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002753 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002754 curproxy->mon_net = defproxy.mon_net;
2755 curproxy->mon_mask = defproxy.mon_mask;
2756 if (defproxy.monitor_uri)
2757 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2758 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002759 if (defproxy.defbe.name)
2760 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002761
2762 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002763 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2764 if (curproxy->conf.logformat_string &&
2765 curproxy->conf.logformat_string != default_http_log_format &&
2766 curproxy->conf.logformat_string != default_tcp_log_format &&
2767 curproxy->conf.logformat_string != clf_http_log_format)
2768 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2769
2770 if (defproxy.conf.lfs_file) {
2771 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2772 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2773 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002774
2775 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2776 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2777 if (curproxy->conf.logformat_sd_string &&
2778 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2779 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2780
2781 if (defproxy.conf.lfsd_file) {
2782 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2783 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2784 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002785 }
2786
2787 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002788 curproxy->timeout.connect = defproxy.timeout.connect;
2789 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002790 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002791 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002792 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002793 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002794 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002795 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002796 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002797 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002798 }
2799
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002801 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002802
2803 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002804 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002805 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002806 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002807 LIST_INIT(&node->list);
2808 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2809 }
2810
Willy Tarreau62a61232013-04-12 18:13:46 +02002811 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2812 if (curproxy->conf.uniqueid_format_string)
2813 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2814
Dragan Dosen43885c72015-10-01 13:18:13 +02002815 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002816
Willy Tarreau62a61232013-04-12 18:13:46 +02002817 if (defproxy.conf.uif_file) {
2818 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2819 curproxy->conf.uif_line = defproxy.conf.uif_line;
2820 }
William Lallemanda73203e2012-03-12 12:48:57 +01002821
2822 /* copy default header unique id */
2823 if (defproxy.header_unique_id)
2824 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2825
William Lallemand82fe75c2012-10-23 10:25:10 +02002826 /* default compression options */
2827 if (defproxy.comp != NULL) {
2828 curproxy->comp = calloc(1, sizeof(struct comp));
2829 curproxy->comp->algos = defproxy.comp->algos;
2830 curproxy->comp->types = defproxy.comp->types;
2831 }
2832
Willy Tarreaubaaee002006-06-26 02:48:02 +02002833 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002834 curproxy->conf.used_listener_id = EB_ROOT;
2835 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002836
Simon Horman98637e52014-06-20 12:30:16 +09002837 if (defproxy.check_path)
2838 curproxy->check_path = strdup(defproxy.check_path);
2839 if (defproxy.check_command)
2840 curproxy->check_command = strdup(defproxy.check_command);
2841
Simon Horman9dc49962015-01-30 11:22:59 +09002842 if (defproxy.email_alert.mailers.name)
2843 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2844 if (defproxy.email_alert.from)
2845 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2846 if (defproxy.email_alert.to)
2847 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2848 if (defproxy.email_alert.myhostname)
2849 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002850 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002851 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002852
Willy Tarreau93893792009-07-23 13:19:11 +02002853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 }
2855 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2856 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002857 /* FIXME-20070101: we should do this too at the end of the
2858 * config parsing to free all default values.
2859 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002860 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2861 err_code |= ERR_ABORT;
2862 goto out;
2863 }
2864
Willy Tarreaua534fea2008-08-03 12:19:50 +02002865 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002866 free(defproxy.check_command);
2867 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002868 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002869 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002870 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002871 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002872 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002873 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002874 free(defproxy.capture_name);
2875 free(defproxy.monitor_uri);
2876 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002877 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002878 free(defproxy.fwdfor_hdr_name);
2879 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002880 free(defproxy.orgto_hdr_name);
2881 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002882 free(defproxy.server_id_hdr_name);
2883 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002884 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002885 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002886 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002887 free(defproxy.expect_regex);
2888 defproxy.expect_regex = NULL;
2889 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002890
Willy Tarreau62a61232013-04-12 18:13:46 +02002891 if (defproxy.conf.logformat_string != default_http_log_format &&
2892 defproxy.conf.logformat_string != default_tcp_log_format &&
2893 defproxy.conf.logformat_string != clf_http_log_format)
2894 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002895
Willy Tarreau62a61232013-04-12 18:13:46 +02002896 free(defproxy.conf.uniqueid_format_string);
2897 free(defproxy.conf.lfs_file);
2898 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002899 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002900 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002901
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002902 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2903 free(defproxy.conf.logformat_sd_string);
2904 free(defproxy.conf.lfsd_file);
2905
Willy Tarreaua534fea2008-08-03 12:19:50 +02002906 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002907 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002908
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 /* we cannot free uri_auth because it might already be used */
2910 init_default_instance();
2911 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002912 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2913 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002914 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }
2917 else if (curproxy == NULL) {
2918 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002922
2923 /* update the current file and line being parsed */
2924 curproxy->conf.args.file = curproxy->conf.file;
2925 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926
2927 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002928 if (!strcmp(args[0], "server") ||
2929 !strcmp(args[0], "default-server") ||
2930 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002931 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2932 if (err_code & ERR_FATAL)
2933 goto out;
2934 }
2935 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002936 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002937 int cur_arg;
2938
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 if (curproxy == &defproxy) {
2940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002944 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002945 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946
Willy Tarreau24709282013-03-10 21:32:12 +01002947 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002948 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002953
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002954 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002955
2956 /* use default settings for unix sockets */
2957 bind_conf->ux.uid = global.unix_bind.ux.uid;
2958 bind_conf->ux.gid = global.unix_bind.ux.gid;
2959 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002960
2961 /* NOTE: the following line might create several listeners if there
2962 * are comma-separated IPs or port ranges. So all further processing
2963 * will have to be applied to all listeners created after last_listen.
2964 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002965 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2966 if (errmsg && *errmsg) {
2967 indent_msg(&errmsg, 2);
2968 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002969 }
2970 else
2971 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2972 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
2975 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002976
Willy Tarreau4348fad2012-09-20 16:48:07 +02002977 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2978 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002979 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002980 }
2981
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002982 cur_arg = 2;
2983 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002984 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002985 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002986 char *err;
2987
Willy Tarreau26982662012-09-12 23:17:10 +02002988 kw = bind_find_kw(args[cur_arg]);
2989 if (kw) {
2990 char *err = NULL;
2991 int code;
2992
2993 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002994 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2995 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002996 cur_arg += 1 + kw->skip ;
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000
Willy Tarreau4348fad2012-09-20 16:48:07 +02003001 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003002 err_code |= code;
3003
3004 if (code) {
3005 if (err && *err) {
3006 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003007 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003008 }
3009 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003010 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3011 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003012 if (code & ERR_FATAL) {
3013 free(err);
3014 cur_arg += 1 + kw->skip;
3015 goto out;
3016 }
3017 }
3018 free(err);
3019 cur_arg += 1 + kw->skip;
3020 continue;
3021 }
3022
Willy Tarreau8638f482012-09-18 18:01:17 +02003023 err = NULL;
3024 if (!bind_dumped) {
3025 bind_dump_kws(&err);
3026 indent_msg(&err, 4);
3027 bind_dumped = 1;
3028 }
3029
3030 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3031 file, linenum, args[0], args[1], args[cur_arg],
3032 err ? " Registered keywords :" : "", err ? err : "");
3033 free(err);
3034
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003037 }
Willy Tarreau93893792009-07-23 13:19:11 +02003038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 }
3040 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003041 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3043 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003049
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 /* flush useless bits */
3051 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003054 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057
William Lallemanddf1425a2015-04-28 20:17:49 +02003058 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3059 goto out;
3060
Willy Tarreau1c47f852006-07-09 08:22:27 +02003061 if (!*args[1]) {
3062 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003066 }
3067
Willy Tarreaua534fea2008-08-03 12:19:50 +02003068 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003069 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003070 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003071 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003072 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3073
Willy Tarreau93893792009-07-23 13:19:11 +02003074 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003077 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3078 goto out;
3079
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3081 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3082 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3083 else {
3084 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 }
3088 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003089 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003090 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003091
3092 if (curproxy == &defproxy) {
3093 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3094 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003097 }
3098
William Lallemanddf1425a2015-04-28 20:17:49 +02003099 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3100 goto out;
3101
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003102 if (!*args[1]) {
3103 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3104 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003107 }
3108
3109 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003110 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003111 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003112
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003113 if (curproxy->uuid <= 0) {
3114 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003115 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003118 }
3119
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003120 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3121 if (node) {
3122 struct proxy *target = container_of(node, struct proxy, conf.id);
3123 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3124 file, linenum, proxy_type_str(curproxy), curproxy->id,
3125 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128 }
3129 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003130 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003131 else if (!strcmp(args[0], "description")) {
3132 int i, len=0;
3133 char *d;
3134
Cyril Bonté99ed3272010-01-24 23:29:44 +01003135 if (curproxy == &defproxy) {
3136 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3137 file, linenum, args[0]);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
3140 }
3141
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003142 if (!*args[1]) {
3143 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3144 file, linenum, args[0]);
3145 return -1;
3146 }
3147
Willy Tarreau348acfe2014-04-14 15:00:39 +02003148 for (i = 1; *args[i]; i++)
3149 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003150
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003151 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003152 curproxy->desc = d;
3153
Willy Tarreau348acfe2014-04-14 15:00:39 +02003154 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3155 for (i = 2; *args[i]; i++)
3156 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003157
3158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003160 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 curproxy->state = PR_STSTOPPED;
3163 }
3164 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003165 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 curproxy->state = PR_STNEW;
3168 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003169 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3170 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003171 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003172
3173 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003174 unsigned int low, high;
3175
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003176 if (strcmp(args[cur_arg], "all") == 0) {
3177 set = 0;
3178 break;
3179 }
3180 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003181 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003182 }
3183 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003184 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003185 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003186 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003187 char *dash = strchr(args[cur_arg], '-');
3188
3189 low = high = str2uic(args[cur_arg]);
3190 if (dash)
3191 high = str2uic(dash + 1);
3192
3193 if (high < low) {
3194 unsigned int swap = low;
3195 low = high;
3196 high = swap;
3197 }
3198
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003199 if (low < 1 || high > LONGBITS) {
3200 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3201 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003204 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003205 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003206 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003207 }
3208 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003209 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3210 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003213 }
3214 cur_arg++;
3215 }
3216 curproxy->bind_proc = set;
3217 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003218 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003219 if (curproxy == &defproxy) {
3220 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003223 }
3224
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003225 err = invalid_char(args[1]);
3226 if (err) {
3227 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3228 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003229 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003230 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003231 }
3232
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003233 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003234 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3235 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003238 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003239 }
3240 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3241
3242 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3243 err_code |= ERR_WARN;
3244
3245 if (*(args[1]) == 0) {
3246 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3247 file, linenum, args[0]);
3248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
3250 }
3251 free(curproxy->dyncookie_key);
3252 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3255 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256
Willy Tarreau977b8e42006-12-29 14:19:17 +01003257 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003259
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 if (*(args[1]) == 0) {
3261 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003266
Willy Tarreau67402132012-05-31 20:40:20 +02003267 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003268 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003269 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003270 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 curproxy->cookie_name = strdup(args[1]);
3272 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003273
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 cur_arg = 2;
3275 while (*(args[cur_arg])) {
3276 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003277 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 }
3279 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003280 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
3282 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003283 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 }
3285 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003286 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 }
3288 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003289 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003291 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003292 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003295 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003297 else if (!strcmp(args[cur_arg], "httponly")) {
3298 curproxy->ck_opts |= PR_CK_HTTPONLY;
3299 }
3300 else if (!strcmp(args[cur_arg], "secure")) {
3301 curproxy->ck_opts |= PR_CK_SECURE;
3302 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003303 else if (!strcmp(args[cur_arg], "domain")) {
3304 if (!*args[cur_arg + 1]) {
3305 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3306 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003309 }
3310
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003311 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003312 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003313 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3314 " dots nor does not start with a dot."
3315 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003316 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003317 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003318 }
3319
3320 err = invalid_domainchar(args[cur_arg + 1]);
3321 if (err) {
3322 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3323 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003326 }
3327
Willy Tarreau68a897b2009-12-03 23:28:34 +01003328 if (!curproxy->cookie_domain) {
3329 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3330 } else {
3331 /* one domain was already specified, add another one by
3332 * building the string which will be returned along with
3333 * the cookie.
3334 */
3335 char *new_ptr;
3336 int new_len = strlen(curproxy->cookie_domain) +
3337 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3338 new_ptr = malloc(new_len);
3339 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3340 free(curproxy->cookie_domain);
3341 curproxy->cookie_domain = new_ptr;
3342 }
Willy Tarreau31936852010-10-06 16:59:56 +02003343 cur_arg++;
3344 }
3345 else if (!strcmp(args[cur_arg], "maxidle")) {
3346 unsigned int maxidle;
3347 const char *res;
3348
3349 if (!*args[cur_arg + 1]) {
3350 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3351 file, linenum, args[cur_arg]);
3352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
3354 }
3355
3356 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3357 if (res) {
3358 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3359 file, linenum, *res, args[cur_arg]);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363 curproxy->cookie_maxidle = maxidle;
3364 cur_arg++;
3365 }
3366 else if (!strcmp(args[cur_arg], "maxlife")) {
3367 unsigned int maxlife;
3368 const char *res;
3369
3370 if (!*args[cur_arg + 1]) {
3371 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3372 file, linenum, args[cur_arg]);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
3376
3377 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3378 if (res) {
3379 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3380 file, linenum, *res, args[cur_arg]);
3381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
3383 }
3384 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003385 cur_arg++;
3386 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003387 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003388
3389 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3390 err_code |= ERR_WARN;
3391 curproxy->ck_opts |= PR_CK_DYNAMIC;
3392 }
3393
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003395 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 +02003396 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400 cur_arg++;
3401 }
Willy Tarreau67402132012-05-31 20:40:20 +02003402 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3404 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
3407
Willy Tarreau67402132012-05-31 20:40:20 +02003408 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3410 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003411 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003413
Willy Tarreau67402132012-05-31 20:40:20 +02003414 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003415 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3416 file, linenum);
3417 err_code |= ERR_ALERT | ERR_FATAL;
3418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003420 else if (!strcmp(args[0], "email-alert")) {
3421 if (*(args[1]) == 0) {
3422 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3423 file, linenum, args[0]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427
3428 if (!strcmp(args[1], "from")) {
3429 if (*(args[1]) == 0) {
3430 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3431 file, linenum, args[1]);
3432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
3434 }
3435 free(curproxy->email_alert.from);
3436 curproxy->email_alert.from = strdup(args[2]);
3437 }
3438 else if (!strcmp(args[1], "mailers")) {
3439 if (*(args[1]) == 0) {
3440 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3441 file, linenum, args[1]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445 free(curproxy->email_alert.mailers.name);
3446 curproxy->email_alert.mailers.name = strdup(args[2]);
3447 }
3448 else if (!strcmp(args[1], "myhostname")) {
3449 if (*(args[1]) == 0) {
3450 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3451 file, linenum, args[1]);
3452 err_code |= ERR_ALERT | ERR_FATAL;
3453 goto out;
3454 }
3455 free(curproxy->email_alert.myhostname);
3456 curproxy->email_alert.myhostname = strdup(args[2]);
3457 }
Simon Horman64e34162015-02-06 11:11:57 +09003458 else if (!strcmp(args[1], "level")) {
3459 curproxy->email_alert.level = get_log_level(args[2]);
3460 if (curproxy->email_alert.level < 0) {
3461 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3462 file, linenum, args[1], args[2]);
3463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
3465 }
3466 }
Simon Horman9dc49962015-01-30 11:22:59 +09003467 else if (!strcmp(args[1], "to")) {
3468 if (*(args[1]) == 0) {
3469 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3470 file, linenum, args[1]);
3471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
3473 }
3474 free(curproxy->email_alert.to);
3475 curproxy->email_alert.to = strdup(args[2]);
3476 }
3477 else {
3478 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3479 file, linenum, args[1]);
3480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
3482 }
Simon Horman64e34162015-02-06 11:11:57 +09003483 /* Indicate that the email_alert is at least partially configured */
3484 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003485 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003486 else if (!strcmp(args[0], "external-check")) {
3487 if (*(args[1]) == 0) {
3488 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3489 file, linenum, args[0]);
3490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
3492 }
3493
3494 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003495 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003496 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003497 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003498 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3499 file, linenum, args[1]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
3502 }
3503 free(curproxy->check_command);
3504 curproxy->check_command = strdup(args[2]);
3505 }
3506 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003507 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003508 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003509 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003510 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3511 file, linenum, args[1]);
3512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
3514 }
3515 free(curproxy->check_path);
3516 curproxy->check_path = strdup(args[2]);
3517 }
3518 else {
3519 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3520 file, linenum, args[1]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003525 else if (!strcmp(args[0], "persist")) { /* persist */
3526 if (*(args[1]) == 0) {
3527 Alert("parsing [%s:%d] : missing persist method.\n",
3528 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003531 }
3532
3533 if (!strncmp(args[1], "rdp-cookie", 10)) {
3534 curproxy->options2 |= PR_O2_RDPC_PRST;
3535
Emeric Brunb982a3d2010-01-04 15:45:53 +01003536 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003537 const char *beg, *end;
3538
3539 beg = args[1] + 11;
3540 end = strchr(beg, ')');
3541
William Lallemanddf1425a2015-04-28 20:17:49 +02003542 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3543 goto out;
3544
Emeric Brun647caf12009-06-30 17:57:00 +02003545 if (!end || end == beg) {
3546 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3547 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003550 }
3551
3552 free(curproxy->rdp_cookie_name);
3553 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3554 curproxy->rdp_cookie_len = end-beg;
3555 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003556 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003557 free(curproxy->rdp_cookie_name);
3558 curproxy->rdp_cookie_name = strdup("msts");
3559 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3560 }
3561 else { /* syntax */
3562 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3563 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003566 }
3567 }
3568 else {
3569 Alert("parsing [%s:%d] : unknown persist method.\n",
3570 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003573 }
3574 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003576 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003580 else if (!strcmp(args[0], "load-server-state-from-file")) {
3581 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3582 err_code |= ERR_WARN;
3583 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3584 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3585 }
3586 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3587 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3588 }
3589 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3590 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3591 }
3592 else {
3593 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3594 file, linenum, args[0], args[1]);
3595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
3597 }
3598 }
3599 else if (!strcmp(args[0], "server-state-file-name")) {
3600 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3601 err_code |= ERR_WARN;
3602 if (*(args[1]) == 0) {
3603 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3604 file, linenum, args[0]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 else if (!strcmp(args[1], "use-backend-name"))
3609 curproxy->server_state_file_name = strdup(curproxy->id);
3610 else
3611 curproxy->server_state_file_name = strdup(args[1]);
3612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003614 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003616
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003618 if (curproxy == &defproxy) {
3619 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623
William Lallemand1a748ae2015-05-19 16:37:23 +02003624 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3625 goto out;
3626
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 if (*(args[4]) == 0) {
3628 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003633 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 curproxy->capture_name = strdup(args[2]);
3635 curproxy->capture_namelen = strlen(curproxy->capture_name);
3636 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 curproxy->to_log |= LW_COOKIE;
3638 }
3639 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3640 struct cap_hdr *hdr;
3641
3642 if (curproxy == &defproxy) {
3643 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 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 }
3647
William Lallemand1a748ae2015-05-19 16:37:23 +02003648 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3649 goto out;
3650
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3652 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3653 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
3657
Vincent Bernat02779b62016-04-03 13:48:43 +02003658 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 hdr->next = curproxy->req_cap;
3660 hdr->name = strdup(args[3]);
3661 hdr->namelen = strlen(args[3]);
3662 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003663 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 hdr->index = curproxy->nb_req_cap++;
3665 curproxy->req_cap = hdr;
3666 curproxy->to_log |= LW_REQHDR;
3667 }
3668 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3669 struct cap_hdr *hdr;
3670
3671 if (curproxy == &defproxy) {
3672 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 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 }
3676
William Lallemand1a748ae2015-05-19 16:37:23 +02003677 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3678 goto out;
3679
Willy Tarreaubaaee002006-06-26 02:48:02 +02003680 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3681 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3682 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003686 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 hdr->next = curproxy->rsp_cap;
3688 hdr->name = strdup(args[3]);
3689 hdr->namelen = strlen(args[3]);
3690 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003691 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 hdr->index = curproxy->nb_rsp_cap++;
3693 curproxy->rsp_cap = hdr;
3694 curproxy->to_log |= LW_RSPHDR;
3695 }
3696 else {
3697 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 }
3702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003703 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003704 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003706
William Lallemanddf1425a2015-04-28 20:17:49 +02003707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3708 goto out;
3709
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 if (*(args[1]) == 0) {
3711 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3712 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
3716 curproxy->conn_retries = atol(args[1]);
3717 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003718 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003719 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003720
3721 if (curproxy == &defproxy) {
3722 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726
Willy Tarreau20b0de52012-12-24 15:45:22 +01003727 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003728 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003729 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3730 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3731 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3732 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003733 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 +01003734 file, linenum, args[0]);
3735 err_code |= ERR_WARN;
3736 }
3737
Willy Tarreauff011f22011-01-06 17:51:27 +01003738 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003739
Willy Tarreauff011f22011-01-06 17:51:27 +01003740 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003741 err_code |= ERR_ALERT | ERR_ABORT;
3742 goto out;
3743 }
3744
Willy Tarreau5002f572014-04-23 01:32:02 +02003745 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003746 err_code |= warnif_cond_conflicts(rule->cond,
3747 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3748 file, linenum);
3749
Willy Tarreauff011f22011-01-06 17:51:27 +01003750 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003751 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003752 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003753 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003754
3755 if (curproxy == &defproxy) {
3756 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
3759 }
3760
3761 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003762 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003763 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3764 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003765 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3766 file, linenum, args[0]);
3767 err_code |= ERR_WARN;
3768 }
3769
3770 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3771
3772 if (!rule) {
3773 err_code |= ERR_ALERT | ERR_ABORT;
3774 goto out;
3775 }
3776
3777 err_code |= warnif_cond_conflicts(rule->cond,
3778 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3779 file, linenum);
3780
3781 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3782 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003783 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3784 /* set the header name and length into the proxy structure */
3785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3786 err_code |= ERR_WARN;
3787
3788 if (!*args[1]) {
3789 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3790 file, linenum, args[0]);
3791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
3793 }
3794
3795 /* set the desired header name */
3796 free(curproxy->server_id_hdr_name);
3797 curproxy->server_id_hdr_name = strdup(args[1]);
3798 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3799 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003800 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003801 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003802
Willy Tarreaub099aca2008-10-12 17:26:37 +02003803 if (curproxy == &defproxy) {
3804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003807 }
3808
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003809 /* emulate "block" using "http-request block". Since these rules are supposed to
3810 * be processed before all http-request rules, we put them into their own list
3811 * and will insert them at the end.
3812 */
3813 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3814 if (!rule) {
3815 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003816 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003817 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003818 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3819 err_code |= warnif_cond_conflicts(rule->cond,
3820 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3821 file, linenum);
3822 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003823
3824 if (!already_warned(WARN_BLOCK_DEPRECATED))
3825 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]);
3826
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003827 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003828 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003829 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003830
Cyril Bonté99ed3272010-01-24 23:29:44 +01003831 if (curproxy == &defproxy) {
3832 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
3835 }
3836
Willy Tarreaube4653b2015-05-28 15:26:58 +02003837 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003838 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3839 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003842 }
3843
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003844 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003845 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003846 err_code |= warnif_cond_conflicts(rule->cond,
3847 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3848 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003849 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003850 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003851 struct switching_rule *rule;
3852
Willy Tarreaub099aca2008-10-12 17:26:37 +02003853 if (curproxy == &defproxy) {
3854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003857 }
3858
Willy Tarreau55ea7572007-06-17 19:56:27 +02003859 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003861
3862 if (*(args[1]) == 0) {
3863 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003866 }
3867
Willy Tarreauf51658d2014-04-23 01:21:56 +02003868 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003869 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003870 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3871 file, linenum, errmsg);
3872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
3874 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003875
Willy Tarreauf51658d2014-04-23 01:21:56 +02003876 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003877 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003878 else if (*args[2]) {
3879 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3880 file, linenum, args[2]);
3881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
3883 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003884
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003885 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003886 if (!rule) {
3887 Alert("Out of memory error.\n");
3888 goto out;
3889 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003890 rule->cond = cond;
3891 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003892 rule->line = linenum;
3893 rule->file = strdup(file);
3894 if (!rule->file) {
3895 Alert("Out of memory error.\n");
3896 goto out;
3897 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003898 LIST_INIT(&rule->list);
3899 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3900 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003901 else if (strcmp(args[0], "use-server") == 0) {
3902 struct server_rule *rule;
3903
3904 if (curproxy == &defproxy) {
3905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
3908 }
3909
3910 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3911 err_code |= ERR_WARN;
3912
3913 if (*(args[1]) == 0) {
3914 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
3917 }
3918
3919 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3920 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3921 file, linenum, args[0]);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
3924 }
3925
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003926 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003927 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3928 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
3931 }
3932
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003933 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003934
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003935 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003936 rule->cond = cond;
3937 rule->srv.name = strdup(args[1]);
3938 LIST_INIT(&rule->list);
3939 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3940 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3941 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003942 else if ((!strcmp(args[0], "force-persist")) ||
3943 (!strcmp(args[0], "ignore-persist"))) {
3944 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003945
3946 if (curproxy == &defproxy) {
3947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
3951
3952 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3953 err_code |= ERR_WARN;
3954
Willy Tarreauef6494c2010-01-28 17:12:36 +01003955 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003956 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3957 file, linenum, args[0]);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
3961
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003962 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003963 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3964 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
3968
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003969 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3970 * where force-persist is applied.
3971 */
3972 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003973
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003974 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003975 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003976 if (!strcmp(args[0], "force-persist")) {
3977 rule->type = PERSIST_TYPE_FORCE;
3978 } else {
3979 rule->type = PERSIST_TYPE_IGNORE;
3980 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003981 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003982 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003983 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003984 else if (!strcmp(args[0], "stick-table")) {
3985 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003986 struct proxy *other;
3987
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003988 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003989 if (other) {
3990 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3991 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003995
Emeric Brun32da3c42010-09-23 18:39:19 +02003996 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003997 curproxy->table.type = (unsigned int)-1;
3998 while (*args[myidx]) {
3999 const char *err;
4000
4001 if (strcmp(args[myidx], "size") == 0) {
4002 myidx++;
4003 if (!*(args[myidx])) {
4004 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4005 file, linenum, args[myidx-1]);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
4009 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4010 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4011 file, linenum, *err, args[myidx-1]);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004015 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004016 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004017 else if (strcmp(args[myidx], "peers") == 0) {
4018 myidx++;
Godbach50523162013-12-11 19:48:57 +08004019 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004020 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4021 file, linenum, args[myidx-1]);
4022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
Godbach50523162013-12-11 19:48:57 +08004024 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004025 curproxy->table.peers.name = strdup(args[myidx++]);
4026 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004027 else if (strcmp(args[myidx], "expire") == 0) {
4028 myidx++;
4029 if (!*(args[myidx])) {
4030 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4031 file, linenum, args[myidx-1]);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
4035 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4036 if (err) {
4037 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4038 file, linenum, *err, args[myidx-1]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004042 if (val > INT_MAX) {
4043 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4044 file, linenum, val);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
4047 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004048 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004049 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004050 }
4051 else if (strcmp(args[myidx], "nopurge") == 0) {
4052 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004053 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004054 }
4055 else if (strcmp(args[myidx], "type") == 0) {
4056 myidx++;
4057 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4058 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4059 file, linenum, args[myidx]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004063 /* myidx already points to next arg */
4064 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004065 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004066 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004067 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004068
4069 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004070 nw = args[myidx];
4071 while (*nw) {
4072 /* the "store" keyword supports a comma-separated list */
4073 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004074 sa = NULL; /* store arg */
4075 while (*nw && *nw != ',') {
4076 if (*nw == '(') {
4077 *nw = 0;
4078 sa = ++nw;
4079 while (*nw != ')') {
4080 if (!*nw) {
4081 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4082 file, linenum, args[0], cw);
4083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
4086 nw++;
4087 }
4088 *nw = '\0';
4089 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004090 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004091 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004092 if (*nw)
4093 *nw++ = '\0';
4094 type = stktable_get_data_type(cw);
4095 if (type < 0) {
4096 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4097 file, linenum, args[0], cw);
4098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
4100 }
Willy Tarreauac782882010-06-20 10:41:54 +02004101
4102 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4103 switch (err) {
4104 case PE_NONE: break;
4105 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004106 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4107 file, linenum, args[0], cw);
4108 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004109 break;
4110
4111 case PE_ARG_MISSING:
4112 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4113 file, linenum, args[0], cw);
4114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
4116
4117 case PE_ARG_NOT_USED:
4118 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4119 file, linenum, args[0], cw);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122
4123 default:
4124 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4125 file, linenum, args[0], cw);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004128 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004129 }
4130 myidx++;
4131 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004132 else {
4133 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4134 file, linenum, args[myidx]);
4135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004137 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004138 }
4139
4140 if (!curproxy->table.size) {
4141 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4142 file, linenum);
4143 err_code |= ERR_ALERT | ERR_FATAL;
4144 goto out;
4145 }
4146
4147 if (curproxy->table.type == (unsigned int)-1) {
4148 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4149 file, linenum);
4150 err_code |= ERR_ALERT | ERR_FATAL;
4151 goto out;
4152 }
4153 }
4154 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004155 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004156 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004157 int myidx = 0;
4158 const char *name = NULL;
4159 int flags;
4160
4161 if (curproxy == &defproxy) {
4162 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
4166
4167 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4168 err_code |= ERR_WARN;
4169 goto out;
4170 }
4171
4172 myidx++;
4173 if ((strcmp(args[myidx], "store") == 0) ||
4174 (strcmp(args[myidx], "store-request") == 0)) {
4175 myidx++;
4176 flags = STK_IS_STORE;
4177 }
4178 else if (strcmp(args[myidx], "store-response") == 0) {
4179 myidx++;
4180 flags = STK_IS_STORE | STK_ON_RSP;
4181 }
4182 else if (strcmp(args[myidx], "match") == 0) {
4183 myidx++;
4184 flags = STK_IS_MATCH;
4185 }
4186 else if (strcmp(args[myidx], "on") == 0) {
4187 myidx++;
4188 flags = STK_IS_MATCH | STK_IS_STORE;
4189 }
4190 else {
4191 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
4194 }
4195
4196 if (*(args[myidx]) == 0) {
4197 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004202 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004203 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004204 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004205 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
4208 }
4209
4210 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004211 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4212 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4213 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004214 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004215 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004216 goto out;
4217 }
4218 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004219 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4220 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4221 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004222 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004223 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004224 goto out;
4225 }
4226 }
4227
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004228 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004229 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004230
Emeric Brunb982a3d2010-01-04 15:45:53 +01004231 if (strcmp(args[myidx], "table") == 0) {
4232 myidx++;
4233 name = args[myidx++];
4234 }
4235
Willy Tarreauef6494c2010-01-28 17:12:36 +01004236 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004237 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004238 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4239 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004240 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004241 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004242 goto out;
4243 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004244 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004245 else if (*(args[myidx])) {
4246 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4247 file, linenum, args[0], args[myidx]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004249 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004250 goto out;
4251 }
Emeric Brun97679e72010-09-23 17:56:44 +02004252 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004253 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004254 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004255 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004256
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004257 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004258 rule->cond = cond;
4259 rule->expr = expr;
4260 rule->flags = flags;
4261 rule->table.name = name ? strdup(name) : NULL;
4262 LIST_INIT(&rule->list);
4263 if (flags & STK_ON_RSP)
4264 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4265 else
4266 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004268 else if (!strcmp(args[0], "stats")) {
4269 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4270 curproxy->uri_auth = NULL; /* we must detach from the default config */
4271
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004272 if (!*args[1]) {
4273 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004274 } else if (!strcmp(args[1], "admin")) {
4275 struct stats_admin_rule *rule;
4276
4277 if (curproxy == &defproxy) {
4278 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
4282
4283 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4284 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4285 err_code |= ERR_ALERT | ERR_ABORT;
4286 goto out;
4287 }
4288
4289 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4290 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4291 file, linenum, args[0], args[1]);
4292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
4294 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004295 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004296 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4297 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
4301
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004302 err_code |= warnif_cond_conflicts(cond,
4303 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4304 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004305
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004306 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004307 rule->cond = cond;
4308 LIST_INIT(&rule->list);
4309 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 } else if (!strcmp(args[1], "uri")) {
4311 if (*(args[2]) == 0) {
4312 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004317 err_code |= ERR_ALERT | ERR_ABORT;
4318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 }
4320 } else if (!strcmp(args[1], "realm")) {
4321 if (*(args[2]) == 0) {
4322 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004325 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4326 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_ABORT;
4328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004330 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004331 unsigned interval;
4332
4333 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4334 if (err) {
4335 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4336 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004339 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4340 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004341 err_code |= ERR_ALERT | ERR_ABORT;
4342 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004343 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004344 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004345 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004346
4347 if (curproxy == &defproxy) {
4348 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
4353 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4354 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4355 err_code |= ERR_ALERT | ERR_ABORT;
4356 goto out;
4357 }
4358
Willy Tarreauff011f22011-01-06 17:51:27 +01004359 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004360 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004361 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4362 file, linenum, args[0]);
4363 err_code |= ERR_WARN;
4364 }
4365
Willy Tarreauff011f22011-01-06 17:51:27 +01004366 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004367
Willy Tarreauff011f22011-01-06 17:51:27 +01004368 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004369 err_code |= ERR_ALERT | ERR_ABORT;
4370 goto out;
4371 }
4372
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004373 err_code |= warnif_cond_conflicts(rule->cond,
4374 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4375 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004376 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004377
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 } else if (!strcmp(args[1], "auth")) {
4379 if (*(args[2]) == 0) {
4380 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4384 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_ABORT;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 }
4388 } else if (!strcmp(args[1], "scope")) {
4389 if (*(args[2]) == 0) {
4390 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4394 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_ABORT;
4396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 }
4398 } else if (!strcmp(args[1], "enable")) {
4399 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_ABORT;
4402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004404 } else if (!strcmp(args[1], "hide-version")) {
4405 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4406 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_ABORT;
4408 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004409 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004410 } else if (!strcmp(args[1], "show-legends")) {
4411 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4412 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4413 err_code |= ERR_ALERT | ERR_ABORT;
4414 goto out;
4415 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004416 } else if (!strcmp(args[1], "show-node")) {
4417
4418 if (*args[2]) {
4419 int i;
4420 char c;
4421
4422 for (i=0; args[2][i]; i++) {
4423 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004424 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4425 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004426 break;
4427 }
4428
4429 if (!i || args[2][i]) {
4430 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4431 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4432 file, linenum, args[0], args[1]);
4433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
4435 }
4436 }
4437
4438 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4439 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4440 err_code |= ERR_ALERT | ERR_ABORT;
4441 goto out;
4442 }
4443 } else if (!strcmp(args[1], "show-desc")) {
4444 char *desc = NULL;
4445
4446 if (*args[2]) {
4447 int i, len=0;
4448 char *d;
4449
Willy Tarreau348acfe2014-04-14 15:00:39 +02004450 for (i = 2; *args[i]; i++)
4451 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004452
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004453 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004454
Willy Tarreau348acfe2014-04-14 15:00:39 +02004455 d += snprintf(d, desc + len - d, "%s", args[2]);
4456 for (i = 3; *args[i]; i++)
4457 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004458 }
4459
4460 if (!*args[2] && !global.desc)
4461 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4462 file, linenum, args[1]);
4463 else {
4464 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4465 free(desc);
4466 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4467 err_code |= ERR_ALERT | ERR_ABORT;
4468 goto out;
4469 }
4470 free(desc);
4471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004473stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004474 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 +01004475 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 }
4479 }
4480 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004481 int optnum;
4482
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004483 if (*(args[1]) == '\0') {
4484 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4485 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004489
4490 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4491 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004492 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4493 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4494 file, linenum, cfg_opts[optnum].name);
4495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
4497 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004498 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4499 goto out;
4500
Willy Tarreau93893792009-07-23 13:19:11 +02004501 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4502 err_code |= ERR_WARN;
4503 goto out;
4504 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004505
Willy Tarreau3842f002009-06-14 11:39:52 +02004506 curproxy->no_options &= ~cfg_opts[optnum].val;
4507 curproxy->options &= ~cfg_opts[optnum].val;
4508
4509 switch (kwm) {
4510 case KWM_STD:
4511 curproxy->options |= cfg_opts[optnum].val;
4512 break;
4513 case KWM_NO:
4514 curproxy->no_options |= cfg_opts[optnum].val;
4515 break;
4516 case KWM_DEF: /* already cleared */
4517 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004518 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004519
Willy Tarreau93893792009-07-23 13:19:11 +02004520 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004521 }
4522 }
4523
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004524 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4525 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004526 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4527 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4528 file, linenum, cfg_opts2[optnum].name);
4529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004532 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4533 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004534 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4535 err_code |= ERR_WARN;
4536 goto out;
4537 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004538
Willy Tarreau3842f002009-06-14 11:39:52 +02004539 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4540 curproxy->options2 &= ~cfg_opts2[optnum].val;
4541
4542 switch (kwm) {
4543 case KWM_STD:
4544 curproxy->options2 |= cfg_opts2[optnum].val;
4545 break;
4546 case KWM_NO:
4547 curproxy->no_options2 |= cfg_opts2[optnum].val;
4548 break;
4549 case KWM_DEF: /* already cleared */
4550 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004551 }
Willy Tarreau93893792009-07-23 13:19:11 +02004552 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004553 }
4554 }
4555
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004556 /* HTTP options override each other. They can be cancelled using
4557 * "no option xxx" which only switches to default mode if the mode
4558 * was this one (useful for cancelling options set in defaults
4559 * sections).
4560 */
4561 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004562 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4563 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004564 if (kwm == KWM_STD) {
4565 curproxy->options &= ~PR_O_HTTP_MODE;
4566 curproxy->options |= PR_O_HTTP_PCL;
4567 goto out;
4568 }
4569 else if (kwm == KWM_NO) {
4570 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4571 curproxy->options &= ~PR_O_HTTP_MODE;
4572 goto out;
4573 }
4574 }
4575 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004576 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4577 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004578 if (kwm == KWM_STD) {
4579 curproxy->options &= ~PR_O_HTTP_MODE;
4580 curproxy->options |= PR_O_HTTP_FCL;
4581 goto out;
4582 }
4583 else if (kwm == KWM_NO) {
4584 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4585 curproxy->options &= ~PR_O_HTTP_MODE;
4586 goto out;
4587 }
4588 }
4589 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004590 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4591 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004592 if (kwm == KWM_STD) {
4593 curproxy->options &= ~PR_O_HTTP_MODE;
4594 curproxy->options |= PR_O_HTTP_SCL;
4595 goto out;
4596 }
4597 else if (kwm == KWM_NO) {
4598 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4599 curproxy->options &= ~PR_O_HTTP_MODE;
4600 goto out;
4601 }
4602 }
4603 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004604 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4605 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004606 if (kwm == KWM_STD) {
4607 curproxy->options &= ~PR_O_HTTP_MODE;
4608 curproxy->options |= PR_O_HTTP_KAL;
4609 goto out;
4610 }
4611 else if (kwm == KWM_NO) {
4612 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4613 curproxy->options &= ~PR_O_HTTP_MODE;
4614 goto out;
4615 }
4616 }
4617 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004618 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4619 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004620 if (kwm == KWM_STD) {
4621 curproxy->options &= ~PR_O_HTTP_MODE;
4622 curproxy->options |= PR_O_HTTP_TUN;
4623 goto out;
4624 }
4625 else if (kwm == KWM_NO) {
4626 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4627 curproxy->options &= ~PR_O_HTTP_MODE;
4628 goto out;
4629 }
4630 }
4631
Joseph Lynch726ab712015-05-11 23:25:34 -07004632 /* Redispatch can take an integer argument that control when the
4633 * resispatch occurs. All values are relative to the retries option.
4634 * This can be cancelled using "no option xxx".
4635 */
4636 if (strcmp(args[1], "redispatch") == 0) {
4637 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4638 err_code |= ERR_WARN;
4639 goto out;
4640 }
4641
4642 curproxy->no_options &= ~PR_O_REDISP;
4643 curproxy->options &= ~PR_O_REDISP;
4644
4645 switch (kwm) {
4646 case KWM_STD:
4647 curproxy->options |= PR_O_REDISP;
4648 curproxy->redispatch_after = -1;
4649 if(*args[2]) {
4650 curproxy->redispatch_after = atol(args[2]);
4651 }
4652 break;
4653 case KWM_NO:
4654 curproxy->no_options |= PR_O_REDISP;
4655 curproxy->redispatch_after = 0;
4656 break;
4657 case KWM_DEF: /* already cleared */
4658 break;
4659 }
4660 goto out;
4661 }
4662
Willy Tarreau3842f002009-06-14 11:39:52 +02004663 if (kwm != KWM_STD) {
4664 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004665 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004668 }
4669
Emeric Brun3a058f32009-06-30 18:26:00 +02004670 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004671 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004673 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004674 if (*(args[2]) != '\0') {
4675 if (!strcmp(args[2], "clf")) {
4676 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004677 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004678 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004679 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004682 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004683 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4684 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004685 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004686 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4687 char *oldlogformat = "log-format";
4688 char *clflogformat = "";
4689
4690 if (curproxy->conf.logformat_string == default_http_log_format)
4691 oldlogformat = "option httplog";
4692 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4693 oldlogformat = "option tcplog";
4694 else if (curproxy->conf.logformat_string == clf_http_log_format)
4695 oldlogformat = "option httplog clf";
4696 if (logformat == clf_http_log_format)
4697 clflogformat = " clf";
4698 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4699 file, linenum, clflogformat, oldlogformat);
4700 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004701 if (curproxy->conf.logformat_string != default_http_log_format &&
4702 curproxy->conf.logformat_string != default_tcp_log_format &&
4703 curproxy->conf.logformat_string != clf_http_log_format)
4704 free(curproxy->conf.logformat_string);
4705 curproxy->conf.logformat_string = logformat;
4706
4707 free(curproxy->conf.lfs_file);
4708 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4709 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004710 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004711 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004712 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4713 char *oldlogformat = "log-format";
4714
4715 if (curproxy->conf.logformat_string == default_http_log_format)
4716 oldlogformat = "option httplog";
4717 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4718 oldlogformat = "option tcplog";
4719 else if (curproxy->conf.logformat_string == clf_http_log_format)
4720 oldlogformat = "option httplog clf";
4721 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4722 file, linenum, oldlogformat);
4723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004725 if (curproxy->conf.logformat_string != default_http_log_format &&
4726 curproxy->conf.logformat_string != default_tcp_log_format &&
4727 curproxy->conf.logformat_string != clf_http_log_format)
4728 free(curproxy->conf.logformat_string);
4729 curproxy->conf.logformat_string = default_tcp_log_format;
4730
4731 free(curproxy->conf.lfs_file);
4732 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4733 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004734
4735 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4736 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004739 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004740 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004741 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004742
William Lallemanddf1425a2015-04-28 20:17:49 +02004743 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4744 goto out;
4745
Willy Tarreau13943ab2006-12-31 00:24:10 +01004746 if (curproxy->cap & PR_CAP_FE)
4747 curproxy->options |= PR_O_TCP_CLI_KA;
4748 if (curproxy->cap & PR_CAP_BE)
4749 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
4751 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004753 err_code |= ERR_WARN;
4754
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004756 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004757 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004758 curproxy->options2 &= ~PR_O2_CHK_ANY;
4759 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 if (!*args[2]) { /* no argument */
4761 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4762 curproxy->check_len = strlen(DEF_CHECK_REQ);
4763 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004764 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004765 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004767 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004769 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 if (*args[4])
4771 reqlen += strlen(args[4]);
4772 else
4773 reqlen += strlen("HTTP/1.0");
4774
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004775 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004777 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004779 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4780 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004781 }
4782 else if (!strcmp(args[1], "ssl-hello-chk")) {
4783 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004786
Willy Tarreaua534fea2008-08-03 12:19:50 +02004787 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004788 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004789 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004790 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004791
4792 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 }
Willy Tarreau23677902007-05-08 23:50:35 +02004795 else if (!strcmp(args[1], "smtpchk")) {
4796 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004797 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004798 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004799 curproxy->options2 &= ~PR_O2_CHK_ANY;
4800 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004801
4802 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4803 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4804 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4805 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4806 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4807 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004808 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004809 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4810 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4811 } else {
4812 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4813 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4814 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4815 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4816 }
4817 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004818 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4819 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004820 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004821 else if (!strcmp(args[1], "pgsql-check")) {
4822 /* use PostgreSQL request to check servers' health */
4823 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4824 err_code |= ERR_WARN;
4825
4826 free(curproxy->check_req);
4827 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004828 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004829 curproxy->options2 |= PR_O2_PGSQL_CHK;
4830
4831 if (*(args[2])) {
4832 int cur_arg = 2;
4833
4834 while (*(args[cur_arg])) {
4835 if (strcmp(args[cur_arg], "user") == 0) {
4836 char * packet;
4837 uint32_t packet_len;
4838 uint32_t pv;
4839
4840 /* suboption header - needs additional argument for it */
4841 if (*(args[cur_arg+1]) == 0) {
4842 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4843 file, linenum, args[0], args[1], args[cur_arg]);
4844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
4846 }
4847
4848 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4849 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4850 pv = htonl(0x30000); /* protocol version 3.0 */
4851
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004852 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004853
4854 memcpy(packet + 4, &pv, 4);
4855
4856 /* copy "user" */
4857 memcpy(packet + 8, "user", 4);
4858
4859 /* copy username */
4860 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4861
4862 free(curproxy->check_req);
4863 curproxy->check_req = packet;
4864 curproxy->check_len = packet_len;
4865
4866 packet_len = htonl(packet_len);
4867 memcpy(packet, &packet_len, 4);
4868 cur_arg += 2;
4869 } else {
4870 /* unknown suboption - catchall */
4871 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4872 file, linenum, args[0], args[1]);
4873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
4875 }
4876 } /* end while loop */
4877 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004878 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4879 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004880 }
4881
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004882 else if (!strcmp(args[1], "redis-check")) {
4883 /* use REDIS PING request to check servers' health */
4884 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4885 err_code |= ERR_WARN;
4886
4887 free(curproxy->check_req);
4888 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004889 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004890 curproxy->options2 |= PR_O2_REDIS_CHK;
4891
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004892 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004893 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4894 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004895
4896 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4897 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004898 }
4899
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004900 else if (!strcmp(args[1], "mysql-check")) {
4901 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004902 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4903 err_code |= ERR_WARN;
4904
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004905 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004906 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004907 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004908 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004909
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004910 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004911 * const char mysql40_client_auth_pkt[] = {
4912 * "\x0e\x00\x00" // packet length
4913 * "\x01" // packet number
4914 * "\x00\x00" // client capabilities
4915 * "\x00\x00\x01" // max packet
4916 * "haproxy\x00" // username (null terminated string)
4917 * "\x00" // filler (always 0x00)
4918 * "\x01\x00\x00" // packet length
4919 * "\x00" // packet number
4920 * "\x01" // COM_QUIT command
4921 * };
4922 */
4923
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004924 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4925 * const char mysql41_client_auth_pkt[] = {
4926 * "\x0e\x00\x00\" // packet length
4927 * "\x01" // packet number
4928 * "\x00\x00\x00\x00" // client capabilities
4929 * "\x00\x00\x00\x01" // max packet
4930 * "\x21" // character set (UTF-8)
4931 * char[23] // All zeroes
4932 * "haproxy\x00" // username (null terminated string)
4933 * "\x00" // filler (always 0x00)
4934 * "\x01\x00\x00" // packet length
4935 * "\x00" // packet number
4936 * "\x01" // COM_QUIT command
4937 * };
4938 */
4939
4940
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004941 if (*(args[2])) {
4942 int cur_arg = 2;
4943
4944 while (*(args[cur_arg])) {
4945 if (strcmp(args[cur_arg], "user") == 0) {
4946 char *mysqluser;
4947 int packetlen, reqlen, userlen;
4948
4949 /* suboption header - needs additional argument for it */
4950 if (*(args[cur_arg+1]) == 0) {
4951 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4952 file, linenum, args[0], args[1], args[cur_arg]);
4953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
4955 }
4956 mysqluser = args[cur_arg + 1];
4957 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004958
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004959 if (*(args[cur_arg+2])) {
4960 if (!strcmp(args[cur_arg+2], "post-41")) {
4961 packetlen = userlen + 7 + 27;
4962 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004963
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004964 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004965 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004966 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004967
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004968 snprintf(curproxy->check_req, 4, "%c%c%c",
4969 ((unsigned char) packetlen & 0xff),
4970 ((unsigned char) (packetlen >> 8) & 0xff),
4971 ((unsigned char) (packetlen >> 16) & 0xff));
4972
4973 curproxy->check_req[3] = 1;
4974 curproxy->check_req[5] = 130;
4975 curproxy->check_req[11] = 1;
4976 curproxy->check_req[12] = 33;
4977 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4978 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4979 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4980 cur_arg += 3;
4981 } else {
4982 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
4985 }
4986 } else {
4987 packetlen = userlen + 7;
4988 reqlen = packetlen + 9;
4989
4990 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004991 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004992 curproxy->check_len = reqlen;
4993
4994 snprintf(curproxy->check_req, 4, "%c%c%c",
4995 ((unsigned char) packetlen & 0xff),
4996 ((unsigned char) (packetlen >> 8) & 0xff),
4997 ((unsigned char) (packetlen >> 16) & 0xff));
4998
4999 curproxy->check_req[3] = 1;
5000 curproxy->check_req[5] = 128;
5001 curproxy->check_req[8] = 1;
5002 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5003 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5004 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5005 cur_arg += 2;
5006 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005007 } else {
5008 /* unknown suboption - catchall */
5009 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5010 file, linenum, args[0], args[1]);
5011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
5013 }
5014 } /* end while loop */
5015 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005016 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005017 else if (!strcmp(args[1], "ldap-check")) {
5018 /* use LDAP request to check servers' health */
5019 free(curproxy->check_req);
5020 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005021 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005022 curproxy->options2 |= PR_O2_LDAP_CHK;
5023
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005024 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005025 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5026 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005027 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5028 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005029 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005030 else if (!strcmp(args[1], "spop-check")) {
5031 if (curproxy == &defproxy) {
5032 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5033 file, linenum, args[0], args[1]);
5034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
5036 }
5037 if (curproxy->cap & PR_CAP_FE) {
5038 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5039 file, linenum, args[0], args[1]);
5040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
5042 }
5043
5044 /* use SPOE request to check servers' health */
5045 free(curproxy->check_req);
5046 curproxy->check_req = NULL;
5047 curproxy->options2 &= ~PR_O2_CHK_ANY;
5048 curproxy->options2 |= PR_O2_SPOP_CHK;
5049
Christopher Faulet8ef75252017-02-20 22:56:03 +01005050 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005051 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
5054 }
5055 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5056 goto out;
5057 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005058 else if (!strcmp(args[1], "tcp-check")) {
5059 /* use raw TCPCHK send/expect to check servers' health */
5060 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5061 err_code |= ERR_WARN;
5062
5063 free(curproxy->check_req);
5064 curproxy->check_req = NULL;
5065 curproxy->options2 &= ~PR_O2_CHK_ANY;
5066 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005067 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5068 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005069 }
Simon Horman98637e52014-06-20 12:30:16 +09005070 else if (!strcmp(args[1], "external-check")) {
5071 /* excute an external command to check servers' health */
5072 free(curproxy->check_req);
5073 curproxy->check_req = NULL;
5074 curproxy->options2 &= ~PR_O2_CHK_ANY;
5075 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005076 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5077 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005078 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005079 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005080 int cur_arg;
5081
5082 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5083 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005084 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005085
Willy Tarreau87cf5142011-08-19 22:57:24 +02005086 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005087
5088 free(curproxy->fwdfor_hdr_name);
5089 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5090 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5091
5092 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5093 cur_arg = 2;
5094 while (*(args[cur_arg])) {
5095 if (!strcmp(args[cur_arg], "except")) {
5096 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005097 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005098 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5099 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005102 }
5103 /* flush useless bits */
5104 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005105 cur_arg += 2;
5106 } else if (!strcmp(args[cur_arg], "header")) {
5107 /* suboption header - needs additional argument for it */
5108 if (*(args[cur_arg+1]) == 0) {
5109 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5110 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005113 }
5114 free(curproxy->fwdfor_hdr_name);
5115 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5116 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5117 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005118 } else if (!strcmp(args[cur_arg], "if-none")) {
5119 curproxy->options &= ~PR_O_FF_ALWAYS;
5120 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005121 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005122 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005123 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005124 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005127 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005128 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005129 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005130 else if (!strcmp(args[1], "originalto")) {
5131 int cur_arg;
5132
5133 /* insert x-original-to field, but not for the IP address listed as an except.
5134 * set default options (ie: bitfield, header name, etc)
5135 */
5136
5137 curproxy->options |= PR_O_ORGTO;
5138
5139 free(curproxy->orgto_hdr_name);
5140 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5141 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5142
Willy Tarreau87cf5142011-08-19 22:57:24 +02005143 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005144 cur_arg = 2;
5145 while (*(args[cur_arg])) {
5146 if (!strcmp(args[cur_arg], "except")) {
5147 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005148 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 +02005149 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5150 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005153 }
5154 /* flush useless bits */
5155 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5156 cur_arg += 2;
5157 } else if (!strcmp(args[cur_arg], "header")) {
5158 /* suboption header - needs additional argument for it */
5159 if (*(args[cur_arg+1]) == 0) {
5160 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5161 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005164 }
5165 free(curproxy->orgto_hdr_name);
5166 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5167 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5168 cur_arg += 2;
5169 } else {
5170 /* unknown suboption - catchall */
5171 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5172 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_ALERT | ERR_FATAL;
5174 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005175 }
5176 } /* end while loop */
5177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 else {
5179 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 }
Willy Tarreau93893792009-07-23 13:19:11 +02005183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005185 else if (!strcmp(args[0], "default_backend")) {
5186 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005188
5189 if (*(args[1]) == 0) {
5190 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005193 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005194 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005195 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005196
5197 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5198 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005201 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005203
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005204 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5205 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 +01005206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 /* enable reconnections to dispatch */
5209 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005210
5211 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005214 else if (!strcmp(args[0], "http-reuse")) {
5215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5216 err_code |= ERR_WARN;
5217
5218 if (strcmp(args[1], "never") == 0) {
5219 /* enable a graceful server shutdown on an HTTP 404 response */
5220 curproxy->options &= ~PR_O_REUSE_MASK;
5221 curproxy->options |= PR_O_REUSE_NEVR;
5222 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5223 goto out;
5224 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005225 else if (strcmp(args[1], "safe") == 0) {
5226 /* enable a graceful server shutdown on an HTTP 404 response */
5227 curproxy->options &= ~PR_O_REUSE_MASK;
5228 curproxy->options |= PR_O_REUSE_SAFE;
5229 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5230 goto out;
5231 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005232 else if (strcmp(args[1], "aggressive") == 0) {
5233 curproxy->options &= ~PR_O_REUSE_MASK;
5234 curproxy->options |= PR_O_REUSE_AGGR;
5235 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5236 goto out;
5237 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005238 else if (strcmp(args[1], "always") == 0) {
5239 /* enable a graceful server shutdown on an HTTP 404 response */
5240 curproxy->options &= ~PR_O_REUSE_MASK;
5241 curproxy->options |= PR_O_REUSE_ALWS;
5242 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5243 goto out;
5244 }
5245 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005246 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
5250 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005251 else if (!strcmp(args[0], "http-check")) {
5252 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005253 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005254
5255 if (strcmp(args[1], "disable-on-404") == 0) {
5256 /* enable a graceful server shutdown on an HTTP 404 response */
5257 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005258 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5259 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005260 }
Willy Tarreauef781042010-01-27 11:53:01 +01005261 else if (strcmp(args[1], "send-state") == 0) {
5262 /* enable emission of the apparent state of a server in HTTP checks */
5263 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005264 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5265 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005266 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005267 else if (strcmp(args[1], "expect") == 0) {
5268 const char *ptr_arg;
5269 int cur_arg;
5270
5271 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5272 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5273 err_code |= ERR_ALERT | ERR_FATAL;
5274 goto out;
5275 }
5276
5277 cur_arg = 2;
5278 /* consider exclamation marks, sole or at the beginning of a word */
5279 while (*(ptr_arg = args[cur_arg])) {
5280 while (*ptr_arg == '!') {
5281 curproxy->options2 ^= PR_O2_EXP_INV;
5282 ptr_arg++;
5283 }
5284 if (*ptr_arg)
5285 break;
5286 cur_arg++;
5287 }
5288 /* now ptr_arg points to the beginning of a word past any possible
5289 * exclamation mark, and cur_arg is the argument which holds this word.
5290 */
5291 if (strcmp(ptr_arg, "status") == 0) {
5292 if (!*(args[cur_arg + 1])) {
5293 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5294 file, linenum, args[0], args[1], ptr_arg);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005299 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005300 curproxy->expect_str = strdup(args[cur_arg + 1]);
5301 }
5302 else if (strcmp(ptr_arg, "string") == 0) {
5303 if (!*(args[cur_arg + 1])) {
5304 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5305 file, linenum, args[0], args[1], ptr_arg);
5306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
5308 }
5309 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005310 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005311 curproxy->expect_str = strdup(args[cur_arg + 1]);
5312 }
5313 else if (strcmp(ptr_arg, "rstatus") == 0) {
5314 if (!*(args[cur_arg + 1])) {
5315 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5316 file, linenum, args[0], args[1], ptr_arg);
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005321 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005322 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005323 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005324 free(curproxy->expect_regex);
5325 curproxy->expect_regex = NULL;
5326 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005327 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005328 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5329 error = NULL;
5330 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5331 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5332 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5333 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
5337 }
5338 else if (strcmp(ptr_arg, "rstring") == 0) {
5339 if (!*(args[cur_arg + 1])) {
5340 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5341 file, linenum, args[0], args[1], ptr_arg);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005346 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005347 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005348 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005349 free(curproxy->expect_regex);
5350 curproxy->expect_regex = NULL;
5351 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005352 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005353 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5354 error = NULL;
5355 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5356 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5357 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5358 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 }
5362 }
5363 else {
5364 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5365 file, linenum, args[0], args[1], ptr_arg);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005370 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005371 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 +02005372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005374 }
5375 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005376 else if (!strcmp(args[0], "tcp-check")) {
5377 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5378 err_code |= ERR_WARN;
5379
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005380 if (strcmp(args[1], "comment") == 0) {
5381 int cur_arg;
5382 struct tcpcheck_rule *tcpcheck;
5383
5384 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005385 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005386 tcpcheck->action = TCPCHK_ACT_COMMENT;
5387
5388 if (!*args[cur_arg + 1]) {
5389 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5390 file, linenum, args[cur_arg]);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
5393 }
5394
5395 tcpcheck->comment = strdup(args[cur_arg + 1]);
5396
5397 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005398 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5399 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005400 }
5401 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005402 const char *ptr_arg;
5403 int cur_arg;
5404 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005405
5406 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005407 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5408 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5409 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5410 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5411 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005412
Willy Tarreau5581c272015-05-13 12:24:53 +02005413 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5414 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5415 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5416 file, linenum);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005419 }
5420
5421 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005422 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005423 tcpcheck->action = TCPCHK_ACT_CONNECT;
5424
5425 /* parsing each parameters to fill up the rule */
5426 while (*(ptr_arg = args[cur_arg])) {
5427 /* tcp port */
5428 if (strcmp(args[cur_arg], "port") == 0) {
5429 if ( (atol(args[cur_arg + 1]) > 65535) ||
5430 (atol(args[cur_arg + 1]) < 1) ){
5431 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5432 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
5435 }
5436 tcpcheck->port = atol(args[cur_arg + 1]);
5437 cur_arg += 2;
5438 }
5439 /* send proxy protocol */
5440 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5441 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5442 cur_arg++;
5443 }
5444#ifdef USE_OPENSSL
5445 else if (strcmp(args[cur_arg], "ssl") == 0) {
5446 curproxy->options |= PR_O_TCPCHK_SSL;
5447 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5448 cur_arg++;
5449 }
5450#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005451 /* comment for this tcpcheck line */
5452 else if (strcmp(args[cur_arg], "comment") == 0) {
5453 if (!*args[cur_arg + 1]) {
5454 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5455 file, linenum, args[cur_arg]);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 }
5459 tcpcheck->comment = strdup(args[cur_arg + 1]);
5460 cur_arg += 2;
5461 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005462 else {
5463#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005464 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 +01005465#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005466 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 +01005467#endif /* USE_OPENSSL */
5468 file, linenum, args[0], args[1], args[cur_arg]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472
5473 }
5474
5475 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5476 }
5477 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005478 if (! *(args[2]) ) {
5479 /* SEND string expected */
5480 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5481 file, linenum, args[0], args[1], args[2]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
5484 } else {
5485 struct tcpcheck_rule *tcpcheck;
5486
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005487 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005488
5489 tcpcheck->action = TCPCHK_ACT_SEND;
5490 tcpcheck->string_len = strlen(args[2]);
5491 tcpcheck->string = strdup(args[2]);
5492 tcpcheck->expect_regex = NULL;
5493
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005494 /* comment for this tcpcheck line */
5495 if (strcmp(args[3], "comment") == 0) {
5496 if (!*args[4]) {
5497 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5498 file, linenum, args[3]);
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
5501 }
5502 tcpcheck->comment = strdup(args[4]);
5503 }
5504
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005505 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5506 }
5507 }
5508 else if (strcmp(args[1], "send-binary") == 0) {
5509 if (! *(args[2]) ) {
5510 /* SEND binary string expected */
5511 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5512 file, linenum, args[0], args[1], args[2]);
5513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
5515 } else {
5516 struct tcpcheck_rule *tcpcheck;
5517 char *err = NULL;
5518
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005519 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005520
5521 tcpcheck->action = TCPCHK_ACT_SEND;
5522 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5523 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5524 file, linenum, args[0], args[1], args[2], err);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528 tcpcheck->expect_regex = NULL;
5529
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005530 /* comment for this tcpcheck line */
5531 if (strcmp(args[3], "comment") == 0) {
5532 if (!*args[4]) {
5533 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5534 file, linenum, args[3]);
5535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
5537 }
5538 tcpcheck->comment = strdup(args[4]);
5539 }
5540
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005541 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5542 }
5543 }
5544 else if (strcmp(args[1], "expect") == 0) {
5545 const char *ptr_arg;
5546 int cur_arg;
5547 int inverse = 0;
5548
5549 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5550 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554
5555 cur_arg = 2;
5556 /* consider exclamation marks, sole or at the beginning of a word */
5557 while (*(ptr_arg = args[cur_arg])) {
5558 while (*ptr_arg == '!') {
5559 inverse = !inverse;
5560 ptr_arg++;
5561 }
5562 if (*ptr_arg)
5563 break;
5564 cur_arg++;
5565 }
5566 /* now ptr_arg points to the beginning of a word past any possible
5567 * exclamation mark, and cur_arg is the argument which holds this word.
5568 */
5569 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005570 struct tcpcheck_rule *tcpcheck;
5571 char *err = NULL;
5572
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005573 if (!*(args[cur_arg + 1])) {
5574 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5575 file, linenum, args[0], args[1], ptr_arg);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005579
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005580 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005581
5582 tcpcheck->action = TCPCHK_ACT_EXPECT;
5583 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5584 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5585 file, linenum, args[0], args[1], args[2], err);
5586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
5588 }
5589 tcpcheck->expect_regex = NULL;
5590 tcpcheck->inverse = inverse;
5591
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005592 /* tcpcheck comment */
5593 cur_arg += 2;
5594 if (strcmp(args[cur_arg], "comment") == 0) {
5595 if (!*args[cur_arg + 1]) {
5596 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5597 file, linenum, args[cur_arg + 1]);
5598 err_code |= ERR_ALERT | ERR_FATAL;
5599 goto out;
5600 }
5601 tcpcheck->comment = strdup(args[cur_arg + 1]);
5602 }
5603
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005604 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5605 }
5606 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005607 struct tcpcheck_rule *tcpcheck;
5608
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005609 if (!*(args[cur_arg + 1])) {
5610 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5611 file, linenum, args[0], args[1], ptr_arg);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005615
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005616 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005617
5618 tcpcheck->action = TCPCHK_ACT_EXPECT;
5619 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5620 tcpcheck->string = strdup(args[cur_arg + 1]);
5621 tcpcheck->expect_regex = NULL;
5622 tcpcheck->inverse = inverse;
5623
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005624 /* tcpcheck comment */
5625 cur_arg += 2;
5626 if (strcmp(args[cur_arg], "comment") == 0) {
5627 if (!*args[cur_arg + 1]) {
5628 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5629 file, linenum, args[cur_arg + 1]);
5630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
5632 }
5633 tcpcheck->comment = strdup(args[cur_arg + 1]);
5634 }
5635
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005636 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5637 }
5638 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005639 struct tcpcheck_rule *tcpcheck;
5640
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005641 if (!*(args[cur_arg + 1])) {
5642 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5643 file, linenum, args[0], args[1], ptr_arg);
5644 err_code |= ERR_ALERT | ERR_FATAL;
5645 goto out;
5646 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005647
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005648 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005649
5650 tcpcheck->action = TCPCHK_ACT_EXPECT;
5651 tcpcheck->string_len = 0;
5652 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005653 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5654 error = NULL;
5655 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5656 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5657 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5658 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
5661 }
5662 tcpcheck->inverse = inverse;
5663
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005664 /* tcpcheck comment */
5665 cur_arg += 2;
5666 if (strcmp(args[cur_arg], "comment") == 0) {
5667 if (!*args[cur_arg + 1]) {
5668 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5669 file, linenum, args[cur_arg + 1]);
5670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
5672 }
5673 tcpcheck->comment = strdup(args[cur_arg + 1]);
5674 }
5675
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005676 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5677 }
5678 else {
5679 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5680 file, linenum, args[0], args[1], ptr_arg);
5681 err_code |= ERR_ALERT | ERR_FATAL;
5682 goto out;
5683 }
5684 }
5685 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005686 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
5689 }
5690 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005691 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005692 if (curproxy == &defproxy) {
5693 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005694 err_code |= ERR_ALERT | ERR_FATAL;
5695 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005696 }
5697
Willy Tarreaub80c2302007-11-30 20:51:32 +01005698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005699 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005700
5701 if (strcmp(args[1], "fail") == 0) {
5702 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005703 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005704 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5705 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005708 }
5709
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005710 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005711 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5712 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005715 }
5716 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5717 }
5718 else {
5719 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005720 err_code |= ERR_ALERT | ERR_FATAL;
5721 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005722 }
5723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724#ifdef TPROXY
5725 else if (!strcmp(args[0], "transparent")) {
5726 /* enable transparent proxy connections */
5727 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005728 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730 }
5731#endif
5732 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005733 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005734 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005735
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736 if (*(args[1]) == 0) {
5737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 }
5741 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005745 else if (!strcmp(args[0], "backlog")) { /* backlog */
5746 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005747 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005748
5749 if (*(args[1]) == 0) {
5750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005753 }
5754 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005755 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5756 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005757 }
Willy Tarreau86034312006-12-29 00:10:33 +01005758 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005759 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005760 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005761
Willy Tarreau86034312006-12-29 00:10:33 +01005762 if (*(args[1]) == 0) {
5763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005766 }
5767 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005768 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5769 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5772 if (*(args[1]) == 0) {
5773 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005774 err_code |= ERR_ALERT | ERR_FATAL;
5775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005776 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005777 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5778 if (err) {
5779 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5780 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005781 err_code |= ERR_ALERT | ERR_FATAL;
5782 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005783 }
5784 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005785 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 }
5788 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005789 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005790 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005791 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005792
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 if (curproxy == &defproxy) {
5794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005798 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005799 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005800
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005801 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005802 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005803 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005804 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005805 goto out;
5806 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005807
5808 proto = protocol_by_family(sk->ss_family);
5809 if (!proto || !proto->connect) {
5810 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5811 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005812 err_code |= ERR_ALERT | ERR_FATAL;
5813 goto out;
5814 }
5815
5816 if (port1 != port2) {
5817 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5818 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005819 err_code |= ERR_ALERT | ERR_FATAL;
5820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005822
5823 if (!port1) {
5824 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5825 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005826 err_code |= ERR_ALERT | ERR_FATAL;
5827 goto out;
5828 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005829
William Lallemanddf1425a2015-04-28 20:17:49 +02005830 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5831 goto out;
5832
Willy Tarreaud5191e72010-02-09 20:50:45 +01005833 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005834 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835 }
5836 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005838 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005839
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005840 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5841 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005846 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005847 /**
5848 * The syntax for hash-type config element is
5849 * hash-type {map-based|consistent} [[<algo>] avalanche]
5850 *
5851 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5852 */
5853 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005854
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5856 err_code |= ERR_WARN;
5857
5858 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005859 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5860 }
5861 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005862 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5863 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005864 else if (strcmp(args[1], "avalanche") == 0) {
5865 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]);
5866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005868 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005869 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005870 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005871 err_code |= ERR_ALERT | ERR_FATAL;
5872 goto out;
5873 }
Bhaskar98634f02013-10-29 23:30:51 -04005874
5875 /* set the hash function to use */
5876 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005877 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005878 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005879
5880 /* if consistent with no argument, then avalanche modifier is also applied */
5881 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5882 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005883 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005884 /* set the hash function */
5885 if (!strcmp(args[2], "sdbm")) {
5886 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5887 }
5888 else if (!strcmp(args[2], "djb2")) {
5889 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005890 }
5891 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005892 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005893 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005894 else if (!strcmp(args[2], "crc32")) {
5895 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5896 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005897 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005898 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 -05005899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
5902
5903 /* set the hash modifier */
5904 if (!strcmp(args[3], "avalanche")) {
5905 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5906 }
5907 else if (*args[3]) {
5908 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5909 err_code |= ERR_ALERT | ERR_FATAL;
5910 goto out;
5911 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005912 }
William Lallemanda73203e2012-03-12 12:48:57 +01005913 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005914 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5915 if (*(args[1]) == 0) {
5916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
5919 }
5920 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5921 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5922 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5923 err_code |= ERR_ALERT | ERR_FATAL;
5924 goto out;
5925 }
5926 }
William Lallemanda73203e2012-03-12 12:48:57 +01005927 else if (strcmp(args[0], "unique-id-format") == 0) {
5928 if (!*(args[1])) {
5929 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
William Lallemand3203ff42012-11-11 17:30:56 +01005933 if (*(args[2])) {
5934 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
5937 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005938 free(curproxy->conf.uniqueid_format_string);
5939 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005940
Willy Tarreau62a61232013-04-12 18:13:46 +02005941 free(curproxy->conf.uif_file);
5942 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5943 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005944 }
William Lallemanda73203e2012-03-12 12:48:57 +01005945
5946 else if (strcmp(args[0], "unique-id-header") == 0) {
5947 if (!*(args[1])) {
5948 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5949 err_code |= ERR_ALERT | ERR_FATAL;
5950 goto out;
5951 }
5952 free(curproxy->header_unique_id);
5953 curproxy->header_unique_id = strdup(args[1]);
5954 }
5955
William Lallemand723b73a2012-02-08 16:37:49 +01005956 else if (strcmp(args[0], "log-format") == 0) {
5957 if (!*(args[1])) {
5958 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5959 err_code |= ERR_ALERT | ERR_FATAL;
5960 goto out;
5961 }
William Lallemand3203ff42012-11-11 17:30:56 +01005962 if (*(args[2])) {
5963 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005967 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5968 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005969
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005970 if (curproxy->conf.logformat_string == default_http_log_format)
5971 oldlogformat = "option httplog";
5972 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5973 oldlogformat = "option tcplog";
5974 else if (curproxy->conf.logformat_string == clf_http_log_format)
5975 oldlogformat = "option httplog clf";
5976 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5977 file, linenum, oldlogformat);
5978 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005979 if (curproxy->conf.logformat_string != default_http_log_format &&
5980 curproxy->conf.logformat_string != default_tcp_log_format &&
5981 curproxy->conf.logformat_string != clf_http_log_format)
5982 free(curproxy->conf.logformat_string);
5983 curproxy->conf.logformat_string = strdup(args[1]);
5984
5985 free(curproxy->conf.lfs_file);
5986 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5987 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005988
5989 /* get a chance to improve log-format error reporting by
5990 * reporting the correct line-number when possible.
5991 */
5992 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5993 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5994 file, linenum, curproxy->id);
5995 err_code |= ERR_WARN;
5996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005998 else if (!strcmp(args[0], "log-format-sd")) {
5999 if (!*(args[1])) {
6000 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6001 err_code |= ERR_ALERT | ERR_FATAL;
6002 goto out;
6003 }
6004 if (*(args[2])) {
6005 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
6008 }
6009
6010 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6011 free(curproxy->conf.logformat_sd_string);
6012 curproxy->conf.logformat_sd_string = strdup(args[1]);
6013
6014 free(curproxy->conf.lfsd_file);
6015 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6016 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6017
6018 /* get a chance to improve log-format-sd error reporting by
6019 * reporting the correct line-number when possible.
6020 */
6021 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6022 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6023 file, linenum, curproxy->id);
6024 err_code |= ERR_WARN;
6025 }
6026 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006027 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6028 if (*(args[1]) == 0) {
6029 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6030 err_code |= ERR_ALERT | ERR_FATAL;
6031 goto out;
6032 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006033 chunk_destroy(&curproxy->log_tag);
6034 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006035 }
William Lallemand0f99e342011-10-12 17:50:54 +02006036 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6037 /* delete previous herited or defined syslog servers */
6038 struct logsrv *back;
6039
6040 if (*(args[1]) != 0) {
6041 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044 }
6045
William Lallemand723b73a2012-02-08 16:37:49 +01006046 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6047 LIST_DEL(&tmplogsrv->list);
6048 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006049 }
6050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006052 struct logsrv *logsrv;
6053
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006055 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006056 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006057 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006058 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006059 LIST_INIT(&node->list);
6060 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062 }
6063 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006064 struct sockaddr_storage *sk;
6065 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006066 int arg = 0;
6067 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006068
Vincent Bernat02779b62016-04-03 13:48:43 +02006069 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006070
Willy Tarreau18324f52014-06-27 18:10:07 +02006071 /* just after the address, a length may be specified */
6072 if (strcmp(args[arg+2], "len") == 0) {
6073 len = atoi(args[arg+3]);
6074 if (len < 80 || len > 65535) {
6075 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6076 file, linenum, args[arg+3]);
6077 err_code |= ERR_ALERT | ERR_FATAL;
6078 goto out;
6079 }
6080 logsrv->maxlen = len;
6081
6082 /* skip these two args */
6083 arg += 2;
6084 }
6085 else
6086 logsrv->maxlen = MAX_SYSLOG_LEN;
6087
Christopher Faulet084aa962017-08-29 16:54:41 +02006088 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006089 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006090
Dragan Dosen1322d092015-09-22 16:05:32 +02006091 /* after the length, a format may be specified */
6092 if (strcmp(args[arg+2], "format") == 0) {
6093 logsrv->format = get_log_format(args[arg+3]);
6094 if (logsrv->format < 0) {
6095 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6096 err_code |= ERR_ALERT | ERR_FATAL;
6097 goto out;
6098 }
6099
6100 /* skip these two args */
6101 arg += 2;
6102 }
6103
William Lallemanddf1425a2015-04-28 20:17:49 +02006104 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6105 goto out;
6106
Willy Tarreau18324f52014-06-27 18:10:07 +02006107 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006108 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006109 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
6112
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
6114
William Lallemand0f99e342011-10-12 17:50:54 +02006115 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006116 if (*(args[arg+3])) {
6117 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006118 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006119 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006120 err_code |= ERR_ALERT | ERR_FATAL;
6121 goto out;
6122
Willy Tarreaubaaee002006-06-26 02:48:02 +02006123 }
6124 }
6125
William Lallemand0f99e342011-10-12 17:50:54 +02006126 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006127 if (*(args[arg+4])) {
6128 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006129 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006130 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
6133
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006134 }
6135 }
6136
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006137 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006138 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006139 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006140 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006141 goto out;
6142 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006143
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006144 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006145
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006146 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006147 if (port1 != port2) {
6148 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6149 file, linenum, args[0], args[1]);
6150 err_code |= ERR_ALERT | ERR_FATAL;
6151 goto out;
6152 }
6153
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006154 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006155 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
William Lallemand0f99e342011-10-12 17:50:54 +02006157
6158 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 }
6160 else {
6161 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6162 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006163 err_code |= ERR_ALERT | ERR_FATAL;
6164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006165 }
6166 }
6167 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006168 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006169 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006170 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006171 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006172
Willy Tarreau977b8e42006-12-29 14:19:17 +01006173 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006174 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006175
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006177 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6178 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006179 err_code |= ERR_ALERT | ERR_FATAL;
6180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006182
6183 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006184 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6185 free(curproxy->conn_src.iface_name);
6186 curproxy->conn_src.iface_name = NULL;
6187 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006188
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006189 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006190 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006191 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006192 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006193 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006194 goto out;
6195 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006196
6197 proto = protocol_by_family(sk->ss_family);
6198 if (!proto || !proto->connect) {
6199 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006200 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006201 err_code |= ERR_ALERT | ERR_FATAL;
6202 goto out;
6203 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006204
6205 if (port1 != port2) {
6206 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6207 file, linenum, args[0], args[1]);
6208 err_code |= ERR_ALERT | ERR_FATAL;
6209 goto out;
6210 }
6211
Willy Tarreauef9a3602012-12-08 22:29:20 +01006212 curproxy->conn_src.source_addr = *sk;
6213 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006214
6215 cur_arg = 2;
6216 while (*(args[cur_arg])) {
6217 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006218#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006219 if (!*args[cur_arg + 1]) {
6220 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6221 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006222 err_code |= ERR_ALERT | ERR_FATAL;
6223 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006224 }
6225
6226 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006227 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6228 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006229 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006230 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6231 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006232 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6233 char *name, *end;
6234
6235 name = args[cur_arg+1] + 7;
6236 while (isspace(*name))
6237 name++;
6238
6239 end = name;
6240 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6241 end++;
6242
Willy Tarreauef9a3602012-12-08 22:29:20 +01006243 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6244 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6245 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6246 curproxy->conn_src.bind_hdr_len = end - name;
6247 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6248 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6249 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006250
6251 /* now look for an occurrence number */
6252 while (isspace(*end))
6253 end++;
6254 if (*end == ',') {
6255 end++;
6256 name = end;
6257 if (*end == '-')
6258 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006259 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006260 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006261 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006262 }
6263
Willy Tarreauef9a3602012-12-08 22:29:20 +01006264 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006265 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6266 " occurrences values smaller than %d.\n",
6267 file, linenum, MAX_HDR_HISTORY);
6268 err_code |= ERR_ALERT | ERR_FATAL;
6269 goto out;
6270 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006271 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006272 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006273
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006274 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006275 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006276 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006277 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006278 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006279 goto out;
6280 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006281
6282 proto = protocol_by_family(sk->ss_family);
6283 if (!proto || !proto->connect) {
6284 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6285 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006286 err_code |= ERR_ALERT | ERR_FATAL;
6287 goto out;
6288 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006289
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006290 if (port1 != port2) {
6291 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6292 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
6295 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006296 curproxy->conn_src.tproxy_addr = *sk;
6297 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006298 }
6299 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006300#else /* no TPROXY support */
6301 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006302 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006303 err_code |= ERR_ALERT | ERR_FATAL;
6304 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006305#endif
6306 cur_arg += 2;
6307 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006308 }
6309
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006310 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6311#ifdef SO_BINDTODEVICE
6312 if (!*args[cur_arg + 1]) {
6313 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6314 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006315 err_code |= ERR_ALERT | ERR_FATAL;
6316 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006317 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006318 free(curproxy->conn_src.iface_name);
6319 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6320 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006321 global.last_checks |= LSTCHK_NETADM;
6322#else
6323 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6324 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006325 err_code |= ERR_ALERT | ERR_FATAL;
6326 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006327#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006328 cur_arg += 2;
6329 continue;
6330 }
6331 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006332 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006333 err_code |= ERR_ALERT | ERR_FATAL;
6334 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006335 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006337 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6338 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6339 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006340 err_code |= ERR_ALERT | ERR_FATAL;
6341 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6346 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006347 err_code |= ERR_ALERT | ERR_FATAL;
6348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350
6351 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006352 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006353 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006354 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356 }
6357 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006359 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006360 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 }
6364 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006366 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
6371 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006373 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 }
6378 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006380 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006381 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006385 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006386 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006387 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006388 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006390 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006396 err_code |= ERR_ALERT | ERR_FATAL;
6397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399
6400 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006401 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006402 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006403 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 }
6406 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006407 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006408 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006409 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006410 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
6413 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006415 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006416 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006417 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 }
6420 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006422 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006423 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
6427 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006429 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006430 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006434 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006436 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006439 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006442 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006443
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 if (curproxy == &defproxy) {
6445 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006449 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006450 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452 if (*(args[1]) == 0) {
6453 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006454 err_code |= ERR_ALERT | ERR_FATAL;
6455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006457
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006458 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006459 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006460 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6461 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006462 err_code |= ERR_ALERT | ERR_FATAL;
6463 goto out;
6464 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006465 err_code |= warnif_cond_conflicts(cond,
6466 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6467 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006468 }
6469 else if (*args[2]) {
6470 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6471 file, linenum, args[0], args[2]);
6472 err_code |= ERR_ALERT | ERR_FATAL;
6473 goto out;
6474 }
6475
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006476 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006477 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006478 wl->s = strdup(args[1]);
6479 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006480 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 }
6482 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6485 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006486 err_code |= ERR_ALERT | ERR_FATAL;
6487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006489
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006491 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006492 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 }
6496 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006497 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006498 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006499 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502 }
6503 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006504 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006505 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006506 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006511 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6513 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006514 err_code |= ERR_ALERT | ERR_FATAL;
6515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 }
6517
Willy Tarreauade5ec42010-01-28 19:33:49 +01006518 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006519 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006520 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006521 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
6524 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006525 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006526 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006527 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006528 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 }
6531 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006532 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006533 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006534 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006535 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
6538 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006539 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006540
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 if (curproxy == &defproxy) {
6542 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006543 err_code |= ERR_ALERT | ERR_FATAL;
6544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006546 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006547 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 if (*(args[1]) == 0) {
6550 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006551 err_code |= ERR_ALERT | ERR_FATAL;
6552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 }
6554
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006555 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006556 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006557 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6558 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006559 err_code |= ERR_ALERT | ERR_FATAL;
6560 goto out;
6561 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006562 err_code |= warnif_cond_conflicts(cond,
6563 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6564 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006565 }
6566 else if (*args[2]) {
6567 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6568 file, linenum, args[0], args[2]);
6569 err_code |= ERR_ALERT | ERR_FATAL;
6570 goto out;
6571 }
6572
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006573 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006574 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006575 wl->s = strdup(args[1]);
6576 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 }
6578 else if (!strcmp(args[0], "errorloc") ||
6579 !strcmp(args[0], "errorloc302") ||
6580 !strcmp(args[0], "errorloc303")) { /* error location */
6581 int errnum, errlen;
6582 char *err;
6583
Willy Tarreau977b8e42006-12-29 14:19:17 +01006584 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006585 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006586
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006588 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006589 err_code |= ERR_ALERT | ERR_FATAL;
6590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591 }
6592
6593 errnum = atol(args[1]);
6594 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006595 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6596 err = malloc(errlen);
6597 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006598 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006599 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6600 err = malloc(errlen);
6601 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 }
6603
Willy Tarreau0f772532006-12-23 20:51:41 +01006604 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6605 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006606 chunk_destroy(&curproxy->errmsg[rc]);
6607 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006608 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006611
6612 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006613 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6614 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006615 free(err);
6616 }
6617 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006618 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6619 int errnum, errlen, fd;
6620 char *err;
6621 struct stat stat;
6622
6623 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006624 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006625
6626 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006627 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_ALERT | ERR_FATAL;
6629 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006630 }
6631
6632 fd = open(args[2], O_RDONLY);
6633 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6634 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6635 file, linenum, args[2], args[1]);
6636 if (fd >= 0)
6637 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006638 err_code |= ERR_ALERT | ERR_FATAL;
6639 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006640 }
6641
Willy Tarreau27a674e2009-08-17 07:23:33 +02006642 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006643 errlen = stat.st_size;
6644 } else {
6645 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006646 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006647 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006648 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006649 }
6650
6651 err = malloc(errlen); /* malloc() must succeed during parsing */
6652 errnum = read(fd, err, errlen);
6653 if (errnum != errlen) {
6654 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6655 file, linenum, args[2], args[1]);
6656 close(fd);
6657 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006658 err_code |= ERR_ALERT | ERR_FATAL;
6659 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006660 }
6661 close(fd);
6662
6663 errnum = atol(args[1]);
6664 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6665 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006666 chunk_destroy(&curproxy->errmsg[rc]);
6667 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006668 break;
6669 }
6670 }
6671
6672 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006673 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6674 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006675 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006676 free(err);
6677 }
6678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006679 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006680 struct cfg_kw_list *kwl;
6681 int index;
6682
6683 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6684 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6685 if (kwl->kw[index].section != CFG_LISTEN)
6686 continue;
6687 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6688 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006689 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006690 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006691 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006692 err_code |= ERR_ALERT | ERR_FATAL;
6693 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006694 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006695 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006696 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006697 err_code |= ERR_WARN;
6698 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006699 }
Willy Tarreau93893792009-07-23 13:19:11 +02006700 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006701 }
6702 }
6703 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006704
Willy Tarreau6daf3432008-01-22 16:44:08 +01006705 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006706 err_code |= ERR_ALERT | ERR_FATAL;
6707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006708 }
Willy Tarreau93893792009-07-23 13:19:11 +02006709 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006710 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006711 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006712}
6713
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006714int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006715cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6716{
6717#ifdef CONFIG_HAP_NS
6718 const char *err;
6719 const char *item = args[0];
6720
6721 if (!strcmp(item, "namespace_list")) {
6722 return 0;
6723 }
6724 else if (!strcmp(item, "namespace")) {
6725 size_t idx = 1;
6726 const char *current;
6727 while (*(current = args[idx++])) {
6728 err = invalid_char(current);
6729 if (err) {
6730 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6731 file, linenum, *err, item, current);
6732 return ERR_ALERT | ERR_FATAL;
6733 }
6734
6735 if (netns_store_lookup(current, strlen(current))) {
6736 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6737 file, linenum, current);
6738 return ERR_ALERT | ERR_FATAL;
6739 }
6740 if (!netns_store_insert(current)) {
6741 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6742 file, linenum, current);
6743 return ERR_ALERT | ERR_FATAL;
6744 }
6745 }
6746 }
6747
6748 return 0;
6749#else
6750 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6751 file, linenum);
6752 return ERR_ALERT | ERR_FATAL;
6753#endif
6754}
6755
6756int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006757cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6758{
6759
6760 int err_code = 0;
6761 const char *err;
6762
6763 if (!strcmp(args[0], "userlist")) { /* new userlist */
6764 struct userlist *newul;
6765
6766 if (!*args[1]) {
6767 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6768 file, linenum, args[0]);
6769 err_code |= ERR_ALERT | ERR_FATAL;
6770 goto out;
6771 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6773 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006774
6775 err = invalid_char(args[1]);
6776 if (err) {
6777 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6778 file, linenum, *err, args[0], args[1]);
6779 err_code |= ERR_ALERT | ERR_FATAL;
6780 goto out;
6781 }
6782
6783 for (newul = userlist; newul; newul = newul->next)
6784 if (!strcmp(newul->name, args[1])) {
6785 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6786 file, linenum, args[1]);
6787 err_code |= ERR_WARN;
6788 goto out;
6789 }
6790
Vincent Bernat02779b62016-04-03 13:48:43 +02006791 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 if (!newul) {
6793 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6794 err_code |= ERR_ALERT | ERR_ABORT;
6795 goto out;
6796 }
6797
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006798 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006799 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6801 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006802 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803 goto out;
6804 }
6805
6806 newul->next = userlist;
6807 userlist = newul;
6808
6809 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006810 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006811 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006812 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813
6814 if (!*args[1]) {
6815 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6816 file, linenum, args[0]);
6817 err_code |= ERR_ALERT | ERR_FATAL;
6818 goto out;
6819 }
6820
6821 err = invalid_char(args[1]);
6822 if (err) {
6823 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6824 file, linenum, *err, args[0], args[1]);
6825 err_code |= ERR_ALERT | ERR_FATAL;
6826 goto out;
6827 }
6828
William Lallemand4ac9f542015-05-28 18:03:51 +02006829 if (!userlist)
6830 goto out;
6831
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006832 for (ag = userlist->groups; ag; ag = ag->next)
6833 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6835 file, linenum, args[1], userlist->name);
6836 err_code |= ERR_ALERT;
6837 goto out;
6838 }
6839
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006840 ag = calloc(1, sizeof(*ag));
6841 if (!ag) {
6842 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6843 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006844 goto out;
6845 }
6846
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006847 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006848 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006849 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6850 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006851 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006852 goto out;
6853 }
6854
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006855 cur_arg = 2;
6856
6857 while (*args[cur_arg]) {
6858 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006859 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006860 cur_arg += 2;
6861 continue;
6862 } else {
6863 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6864 file, linenum, args[0]);
6865 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006866 free(ag->groupusers);
6867 free(ag->name);
6868 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006869 goto out;
6870 }
6871 }
6872
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006873 ag->next = userlist->groups;
6874 userlist->groups = ag;
6875
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006876 } else if (!strcmp(args[0], "user")) { /* new user */
6877 struct auth_users *newuser;
6878 int cur_arg;
6879
6880 if (!*args[1]) {
6881 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6882 file, linenum, args[0]);
6883 err_code |= ERR_ALERT | ERR_FATAL;
6884 goto out;
6885 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006886 if (!userlist)
6887 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006888
6889 for (newuser = userlist->users; newuser; newuser = newuser->next)
6890 if (!strcmp(newuser->user, args[1])) {
6891 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6892 file, linenum, args[1], userlist->name);
6893 err_code |= ERR_ALERT;
6894 goto out;
6895 }
6896
Vincent Bernat02779b62016-04-03 13:48:43 +02006897 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006898 if (!newuser) {
6899 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6900 err_code |= ERR_ALERT | ERR_ABORT;
6901 goto out;
6902 }
6903
6904 newuser->user = strdup(args[1]);
6905
6906 newuser->next = userlist->users;
6907 userlist->users = newuser;
6908
6909 cur_arg = 2;
6910
6911 while (*args[cur_arg]) {
6912 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006913#ifdef CONFIG_HAP_CRYPT
6914 if (!crypt("", args[cur_arg + 1])) {
6915 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6916 file, linenum, newuser->user);
6917 err_code |= ERR_ALERT | ERR_FATAL;
6918 goto out;
6919 }
6920#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006921 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6922 file, linenum);
6923 err_code |= ERR_ALERT;
6924#endif
6925 newuser->pass = strdup(args[cur_arg + 1]);
6926 cur_arg += 2;
6927 continue;
6928 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6929 newuser->pass = strdup(args[cur_arg + 1]);
6930 newuser->flags |= AU_O_INSECURE;
6931 cur_arg += 2;
6932 continue;
6933 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006934 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006935 cur_arg += 2;
6936 continue;
6937 } else {
6938 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6939 file, linenum, args[0]);
6940 err_code |= ERR_ALERT | ERR_FATAL;
6941 goto out;
6942 }
6943 }
6944 } else {
6945 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6946 err_code |= ERR_ALERT | ERR_FATAL;
6947 }
6948
6949out:
6950 return err_code;
6951}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006952
Christopher Faulet79bdef32016-11-04 22:36:15 +01006953int
6954cfg_parse_scope(const char *file, int linenum, char *line)
6955{
6956 char *beg, *end, *scope = NULL;
6957 int err_code = 0;
6958 const char *err;
6959
6960 beg = line + 1;
6961 end = strchr(beg, ']');
6962
6963 /* Detect end of scope declaration */
6964 if (!end || end == beg) {
6965 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6966 file, linenum);
6967 err_code |= ERR_ALERT | ERR_FATAL;
6968 goto out;
6969 }
6970
6971 /* Get scope name and check its validity */
6972 scope = my_strndup(beg, end-beg);
6973 err = invalid_char(scope);
6974 if (err) {
6975 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6976 file, linenum, *err);
6977 err_code |= ERR_ALERT | ERR_ABORT;
6978 goto out;
6979 }
6980
6981 /* Be sure to have a scope declaration alone on its line */
6982 line = end+1;
6983 while (isspace((unsigned char)*line))
6984 line++;
6985 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6986 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6987 file, linenum, *line);
6988 err_code |= ERR_ALERT | ERR_ABORT;
6989 goto out;
6990 }
6991
6992 /* We have a valid scope declaration, save it */
6993 free(cfg_scope);
6994 cfg_scope = scope;
6995 scope = NULL;
6996
6997 out:
6998 free(scope);
6999 return err_code;
7000}
7001
Willy Tarreaubaaee002006-06-26 02:48:02 +02007002/*
7003 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007004 * Returns the error code, 0 if OK, or any combination of :
7005 * - ERR_ABORT: must abort ASAP
7006 * - ERR_FATAL: we can continue parsing but not start the service
7007 * - ERR_WARN: a warning has been emitted
7008 * - ERR_ALERT: an alert has been emitted
7009 * Only the two first ones can stop processing, the two others are just
7010 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007012int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013{
William Lallemand64e84512015-05-12 14:25:37 +02007014 char *thisline;
7015 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 FILE *f;
7017 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007018 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007019 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007020 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007021 int readbytes = 0;
7022
7023 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007024 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007025 return -1;
7026 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007027
David Carlier97880bb2016-04-08 10:35:26 +01007028 if ((f=fopen(file,"r")) == NULL) {
7029 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007030 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032
William Lallemandb2f07452015-05-12 14:27:13 +02007033next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007034 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007035 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007036 char *end;
7037 char *args[MAX_LINE_ARGS + 1];
7038 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007039 int dquote = 0; /* double quote */
7040 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007041
Willy Tarreaubaaee002006-06-26 02:48:02 +02007042 linenum++;
7043
7044 end = line + strlen(line);
7045
William Lallemand64e84512015-05-12 14:25:37 +02007046 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007047 /* Check if we reached the limit and the last char is not \n.
7048 * Watch out for the last line without the terminating '\n'!
7049 */
William Lallemand64e84512015-05-12 14:25:37 +02007050 char *newline;
7051 int newlinesize = linesize * 2;
7052
7053 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7054 if (newline == NULL) {
7055 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7056 file, linenum);
7057 err_code |= ERR_ALERT | ERR_FATAL;
7058 continue;
7059 }
7060
7061 readbytes = linesize - 1;
7062 linesize = newlinesize;
7063 thisline = newline;
7064 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007065 }
7066
William Lallemand64e84512015-05-12 14:25:37 +02007067 readbytes = 0;
7068
Willy Tarreaubaaee002006-06-26 02:48:02 +02007069 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007070 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007072
Christopher Faulet79bdef32016-11-04 22:36:15 +01007073
7074 if (*line == '[') {/* This is the begining if a scope */
7075 err_code |= cfg_parse_scope(file, linenum, line);
7076 goto next_line;
7077 }
7078
Willy Tarreaubaaee002006-06-26 02:48:02 +02007079 arg = 0;
7080 args[arg] = line;
7081
7082 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007083 if (*line == '"' && !squote) { /* double quote outside single quotes */
7084 if (dquote)
7085 dquote = 0;
7086 else
7087 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007088 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007089 end--;
7090 }
7091 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7092 if (squote)
7093 squote = 0;
7094 else
7095 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007096 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007097 end--;
7098 }
7099 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007100 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7101 * C equivalent value. Other combinations left unchanged (eg: \1).
7102 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007103 int skip = 0;
7104 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7105 *line = line[1];
7106 skip = 1;
7107 }
7108 else if (line[1] == 'r') {
7109 *line = '\r';
7110 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007112 else if (line[1] == 'n') {
7113 *line = '\n';
7114 skip = 1;
7115 }
7116 else if (line[1] == 't') {
7117 *line = '\t';
7118 skip = 1;
7119 }
7120 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007121 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007122 unsigned char hex1, hex2;
7123 hex1 = toupper(line[2]) - '0';
7124 hex2 = toupper(line[3]) - '0';
7125 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7126 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7127 *line = (hex1<<4) + hex2;
7128 skip = 3;
7129 }
7130 else {
7131 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007132 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007134 } else if (line[1] == '"') {
7135 *line = '"';
7136 skip = 1;
7137 } else if (line[1] == '\'') {
7138 *line = '\'';
7139 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007140 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7141 *line = '$';
7142 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 }
7144 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007145 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007146 end -= skip;
7147 }
7148 line++;
7149 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007150 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007151 /* end of string, end of loop */
7152 *line = 0;
7153 break;
7154 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007155 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007156 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007157 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007158 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 line++;
7160 args[++arg] = line;
7161 }
William Lallemandb2f07452015-05-12 14:27:13 +02007162 else if (dquote && *line == '$') {
7163 /* environment variables are evaluated inside double quotes */
7164 char *var_beg;
7165 char *var_end;
7166 char save_char;
7167 char *value;
7168 int val_len;
7169 int newlinesize;
7170 int braces = 0;
7171
7172 var_beg = line + 1;
7173 var_end = var_beg;
7174
7175 if (*var_beg == '{') {
7176 var_beg++;
7177 var_end++;
7178 braces = 1;
7179 }
7180
7181 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7182 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7183 err_code |= ERR_ALERT | ERR_FATAL;
7184 goto next_line; /* skip current line */
7185 }
7186
7187 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7188 var_end++;
7189
7190 save_char = *var_end;
7191 *var_end = '\0';
7192 value = getenv(var_beg);
7193 *var_end = save_char;
7194 val_len = value ? strlen(value) : 0;
7195
7196 if (braces) {
7197 if (*var_end == '}') {
7198 var_end++;
7199 braces = 0;
7200 } else {
7201 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7202 err_code |= ERR_ALERT | ERR_FATAL;
7203 goto next_line; /* skip current line */
7204 }
7205 }
7206
7207 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7208
7209 /* if not enough space in thisline */
7210 if (newlinesize > linesize) {
7211 char *newline;
7212
7213 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7214 if (newline == NULL) {
7215 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7216 err_code |= ERR_ALERT | ERR_FATAL;
7217 goto next_line; /* slip current line */
7218 }
7219 /* recompute pointers if realloc returns a new pointer */
7220 if (newline != thisline) {
7221 int i;
7222 int diff;
7223
7224 for (i = 0; i <= arg; i++) {
7225 diff = args[i] - thisline;
7226 args[i] = newline + diff;
7227 }
7228
7229 diff = var_end - thisline;
7230 var_end = newline + diff;
7231 diff = end - thisline;
7232 end = newline + diff;
7233 diff = line - thisline;
7234 line = newline + diff;
7235 thisline = newline;
7236 }
7237 linesize = newlinesize;
7238 }
7239
7240 /* insert value inside the line */
7241 memmove(line + val_len, var_end, end - var_end + 1);
7242 memcpy(line, value, val_len);
7243 end += val_len - (var_end - line);
7244 line += val_len;
7245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007246 else {
7247 line++;
7248 }
7249 }
William Lallemandb2f07452015-05-12 14:27:13 +02007250
William Lallemandf9873ba2015-05-05 17:37:14 +02007251 if (dquote) {
7252 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7253 err_code |= ERR_ALERT | ERR_FATAL;
7254 }
7255
7256 if (squote) {
7257 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7258 err_code |= ERR_ALERT | ERR_FATAL;
7259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007260
7261 /* empty line */
7262 if (!**args)
7263 continue;
7264
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007265 if (*line) {
7266 /* we had to stop due to too many args.
7267 * Let's terminate the string, print the offending part then cut the
7268 * last arg.
7269 */
7270 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7271 line++;
7272 *line = '\0';
7273
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007274 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007275 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007276 err_code |= ERR_ALERT | ERR_FATAL;
7277 args[arg] = line;
7278 }
7279
Willy Tarreau540abe42007-05-02 20:50:16 +02007280 /* zero out remaining args and ensure that at least one entry
7281 * is zeroed out.
7282 */
7283 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007284 args[arg] = line;
7285 }
7286
Willy Tarreau3842f002009-06-14 11:39:52 +02007287 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007288 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007289 char *tmp;
7290
Willy Tarreau3842f002009-06-14 11:39:52 +02007291 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007292 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007293 for (arg=0; *args[arg+1]; arg++)
7294 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007295 *tmp = '\0'; // fix the next arg to \0
7296 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007297 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007298 else if (!strcmp(args[0], "default")) {
7299 kwm = KWM_DEF;
7300 for (arg=0; *args[arg+1]; arg++)
7301 args[arg] = args[arg+1]; // shift args after inversion
7302 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007303
William Lallemand0f99e342011-10-12 17:50:54 +02007304 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7305 strcmp(args[0], "log") != 0) {
7306 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007307 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007308 }
7309
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007310 /* detect section start */
7311 list_for_each_entry(ics, &sections, list) {
7312 if (strcmp(args[0], ics->section_name) == 0) {
7313 cursection = ics->section_name;
7314 cs = ics;
7315 break;
7316 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007317 }
7318
William Lallemandd2ff56d2017-10-16 11:06:50 +02007319 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007320 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007321 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007322 } else {
7323 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007324
William Lallemandd2ff56d2017-10-16 11:06:50 +02007325 if (pcs != cs && pcs && pcs->post_section_parser) {
7326 err_code |= pcs->post_section_parser();
7327 if (err_code & ERR_ABORT)
7328 goto err;
7329 }
7330
7331 err_code |= cs->section_parser(file, linenum, args, kwm);
7332 if (err_code & ERR_ABORT)
7333 goto err;
7334 }
7335 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007336 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007337
7338 if (pcs == cs && pcs && pcs->post_section_parser)
7339 err_code |= pcs->post_section_parser();
7340
7341err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007342 free(cfg_scope);
7343 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007344 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007345 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007346 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007347 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007348}
7349
Willy Tarreau64ab6072014-09-16 12:17:36 +02007350/* This function propagates processes from frontend <from> to backend <to> so
7351 * that it is always guaranteed that a backend pointed to by a frontend is
7352 * bound to all of its processes. After that, if the target is a "listen"
7353 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007354 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007355 * checked first to ensure that <to> is already bound to all processes of
7356 * <from>, there is no risk of looping and we ensure to follow the shortest
7357 * path to the destination.
7358 *
7359 * It is possible to set <to> to NULL for the first call so that the function
7360 * takes care of visiting the initial frontend in <from>.
7361 *
7362 * It is important to note that the function relies on the fact that all names
7363 * have already been resolved.
7364 */
7365void propagate_processes(struct proxy *from, struct proxy *to)
7366{
7367 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007368
7369 if (to) {
7370 /* check whether we need to go down */
7371 if (from->bind_proc &&
7372 (from->bind_proc & to->bind_proc) == from->bind_proc)
7373 return;
7374
7375 if (!from->bind_proc && !to->bind_proc)
7376 return;
7377
7378 to->bind_proc = from->bind_proc ?
7379 (to->bind_proc | from->bind_proc) : 0;
7380
7381 /* now propagate down */
7382 from = to;
7383 }
7384
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007385 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007386 return;
7387
Willy Tarreauf6b70012014-12-18 14:00:43 +01007388 if (from->state == PR_STSTOPPED)
7389 return;
7390
Willy Tarreau64ab6072014-09-16 12:17:36 +02007391 /* default_backend */
7392 if (from->defbe.be)
7393 propagate_processes(from, from->defbe.be);
7394
7395 /* use_backend */
7396 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007397 if (rule->dynamic)
7398 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007399 to = rule->be.backend;
7400 propagate_processes(from, to);
7401 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007402}
7403
Willy Tarreaubb925012009-07-23 13:36:36 +02007404/*
7405 * Returns the error code, 0 if OK, or any combination of :
7406 * - ERR_ABORT: must abort ASAP
7407 * - ERR_FATAL: we can continue parsing but not start the service
7408 * - ERR_WARN: a warning has been emitted
7409 * - ERR_ALERT: an alert has been emitted
7410 * Only the two first ones can stop processing, the two others are just
7411 * indicators.
7412 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007413int check_config_validity()
7414{
7415 int cfgerr = 0;
7416 struct proxy *curproxy = NULL;
7417 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007418 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007419 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007420 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007421 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007422 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007423
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007424 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007425 /*
7426 * Now, check for the integrity of all that we have collected.
7427 */
7428
7429 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007430 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007431
Willy Tarreau193b8c62012-11-22 00:17:38 +01007432 if (!global.tune.max_http_hdr)
7433 global.tune.max_http_hdr = MAX_HTTP_HDR;
7434
7435 if (!global.tune.cookie_len)
7436 global.tune.cookie_len = CAPTURE_LEN;
7437
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007438 if (!global.tune.requri_len)
7439 global.tune.requri_len = REQURI_LEN;
7440
Emeric Brun96fd9262017-07-05 13:33:16 +02007441 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7442
Willy Tarreau193b8c62012-11-22 00:17:38 +01007443 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7444
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007445 /* Post initialisation of the users and groups lists. */
7446 err_code = userlist_postinit();
7447 if (err_code != ERR_NONE)
7448 goto out;
7449
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007450 /* first, we will invert the proxy list order */
7451 curproxy = NULL;
7452 while (proxy) {
7453 struct proxy *next;
7454
7455 next = proxy->next;
7456 proxy->next = curproxy;
7457 curproxy = proxy;
7458 if (!next)
7459 break;
7460 proxy = next;
7461 }
7462
Willy Tarreau419ead82014-09-16 13:41:21 +02007463 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007464 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007465 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007466 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007467 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007468 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007469 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007470 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007471
Willy Tarreau050536d2012-10-04 08:47:34 +02007472 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007473 /* proxy ID not set, use automatic numbering with first
7474 * spare entry starting with next_pxid.
7475 */
7476 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7477 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7478 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007479 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007480 next_pxid++;
7481
Willy Tarreau55ea7572007-06-17 19:56:27 +02007482
Willy Tarreaubaaee002006-06-26 02:48:02 +02007483 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007484 /* ensure we don't keep listeners uselessly bound */
7485 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007486 free((void *)curproxy->table.peers.name);
7487 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007488 continue;
7489 }
7490
Willy Tarreau102df612014-05-07 23:56:38 +02007491 /* Check multi-process mode compatibility for the current proxy */
7492
7493 if (curproxy->bind_proc) {
7494 /* an explicit bind-process was specified, let's check how many
7495 * processes remain.
7496 */
David Carliere6c39412015-07-02 07:00:17 +00007497 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007498
7499 curproxy->bind_proc &= nbits(global.nbproc);
7500 if (!curproxy->bind_proc && nbproc == 1) {
7501 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);
7502 curproxy->bind_proc = 1;
7503 }
7504 else if (!curproxy->bind_proc && nbproc > 1) {
7505 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);
7506 curproxy->bind_proc = 0;
7507 }
7508 }
7509
Willy Tarreau3d209582014-05-09 17:06:11 +02007510 /* check and reduce the bind-proc of each listener */
7511 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7512 unsigned long mask;
7513
7514 if (!bind_conf->bind_proc)
7515 continue;
7516
7517 mask = nbits(global.nbproc);
7518 if (curproxy->bind_proc)
7519 mask &= curproxy->bind_proc;
7520 /* mask cannot be null here thanks to the previous checks */
7521
David Carliere6c39412015-07-02 07:00:17 +00007522 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007523 bind_conf->bind_proc &= mask;
7524
7525 if (!bind_conf->bind_proc && nbproc == 1) {
7526 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",
7527 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7528 bind_conf->bind_proc = mask & ~(mask - 1);
7529 }
7530 else if (!bind_conf->bind_proc && nbproc > 1) {
7531 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",
7532 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7533 bind_conf->bind_proc = 0;
7534 }
7535 }
7536
Willy Tarreauff01a212009-03-15 13:46:16 +01007537 switch (curproxy->mode) {
7538 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007539 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007540 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007541 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7542 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007543 cfgerr++;
7544 }
7545
7546 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007547 Warning("config : servers will be ignored for %s '%s'.\n",
7548 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007549 break;
7550
7551 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007552 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007553 break;
7554
7555 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007556 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007557 break;
7558 }
7559
Willy Tarreauf3934b82015-08-11 11:36:45 +02007560 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7561 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7562 proxy_type_str(curproxy), curproxy->id);
7563 err_code |= ERR_WARN;
7564 }
7565
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007566 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007567 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007568 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007569 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007571 cfgerr++;
7572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007573#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007574 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007575 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7576 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007577 cfgerr++;
7578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007579#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007580 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007581 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7582 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007583 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007584 }
7585 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007586 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007587 /* If no LB algo is set in a backend, and we're not in
7588 * transparent mode, dispatch mode nor proxy mode, we
7589 * want to use balance roundrobin by default.
7590 */
7591 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7592 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007593 }
7594 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007595
Willy Tarreau1620ec32011-08-06 17:05:02 +02007596 if (curproxy->options & PR_O_DISPATCH)
7597 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7598 else if (curproxy->options & PR_O_HTTP_PROXY)
7599 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7600 else if (curproxy->options & PR_O_TRANSP)
7601 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007602
Willy Tarreau1620ec32011-08-06 17:05:02 +02007603 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7604 if (curproxy->options & PR_O_DISABLE404) {
7605 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7606 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7607 err_code |= ERR_WARN;
7608 curproxy->options &= ~PR_O_DISABLE404;
7609 }
7610 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7611 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7612 "send-state", proxy_type_str(curproxy), curproxy->id);
7613 err_code |= ERR_WARN;
7614 curproxy->options &= ~PR_O2_CHK_SNDST;
7615 }
Willy Tarreauef781042010-01-27 11:53:01 +01007616 }
7617
Simon Horman98637e52014-06-20 12:30:16 +09007618 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7619 if (!global.external_check) {
7620 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7621 curproxy->id, "option external-check");
7622 cfgerr++;
7623 }
7624 if (!curproxy->check_command) {
7625 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7626 curproxy->id, "option external-check");
7627 cfgerr++;
7628 }
7629 }
7630
Simon Horman64e34162015-02-06 11:11:57 +09007631 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007632 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7633 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007634 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7635 "'email-alert myhostname', or 'email-alert to' "
7636 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007637 "to be present).\n",
7638 proxy_type_str(curproxy), curproxy->id);
7639 err_code |= ERR_WARN;
7640 free_email_alert(curproxy);
7641 }
7642 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007643 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007644 }
7645
Simon Horman98637e52014-06-20 12:30:16 +09007646 if (curproxy->check_command) {
7647 int clear = 0;
7648 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7649 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7650 "external-check command", proxy_type_str(curproxy), curproxy->id);
7651 err_code |= ERR_WARN;
7652 clear = 1;
7653 }
7654 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007655 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007656 curproxy->id, "external-check command");
7657 cfgerr++;
7658 }
7659 if (clear) {
7660 free(curproxy->check_command);
7661 curproxy->check_command = NULL;
7662 }
7663 }
7664
7665 if (curproxy->check_path) {
7666 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7667 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7668 "external-check path", proxy_type_str(curproxy), curproxy->id);
7669 err_code |= ERR_WARN;
7670 free(curproxy->check_path);
7671 curproxy->check_path = NULL;
7672 }
7673 }
7674
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007675 /* if a default backend was specified, let's find it */
7676 if (curproxy->defbe.name) {
7677 struct proxy *target;
7678
Willy Tarreauafb39922015-05-26 12:04:09 +02007679 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007680 if (!target) {
7681 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7682 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007683 cfgerr++;
7684 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007685 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7686 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007687 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007688 } else if (target->mode != curproxy->mode &&
7689 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7690
7691 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7692 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7693 curproxy->conf.file, curproxy->conf.line,
7694 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7695 target->conf.file, target->conf.line);
7696 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007697 } else {
7698 free(curproxy->defbe.name);
7699 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007700 /* Update tot_fe_maxconn for a further fullconn's computation */
7701 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007702 /* Emit a warning if this proxy also has some servers */
7703 if (curproxy->srv) {
7704 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7705 curproxy->id);
7706 err_code |= ERR_WARN;
7707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007708 }
7709 }
7710
Emeric Brun3f783572017-01-12 11:21:28 +01007711 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7712 /* Case of listen without default backend
7713 * The curproxy will be its own default backend
7714 * so we update tot_fe_maxconn for a further
7715 * fullconn's computation */
7716 curproxy->tot_fe_maxconn += curproxy->maxconn;
7717 }
7718
Willy Tarreau55ea7572007-06-17 19:56:27 +02007719 /* find the target proxy for 'use_backend' rules */
7720 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007721 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007722 struct logformat_node *node;
7723 char *pxname;
7724
7725 /* Try to parse the string as a log format expression. If the result
7726 * of the parsing is only one entry containing a simple string, then
7727 * it's a standard string corresponding to a static rule, thus the
7728 * parsing is cancelled and be.name is restored to be resolved.
7729 */
7730 pxname = rule->be.name;
7731 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007732 curproxy->conf.args.ctx = ARGC_UBK;
7733 curproxy->conf.args.file = rule->file;
7734 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007735 err = NULL;
7736 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7737 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7738 rule->file, rule->line, pxname, err);
7739 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007740 cfgerr++;
7741 continue;
7742 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007743 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7744
7745 if (!LIST_ISEMPTY(&rule->be.expr)) {
7746 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7747 rule->dynamic = 1;
7748 free(pxname);
7749 continue;
7750 }
7751 /* simple string: free the expression and fall back to static rule */
7752 free(node->arg);
7753 free(node);
7754 }
7755
7756 rule->dynamic = 0;
7757 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007758
Willy Tarreauafb39922015-05-26 12:04:09 +02007759 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007760 if (!target) {
7761 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7762 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007763 cfgerr++;
7764 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007765 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7766 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007767 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007768 } else if (target->mode != curproxy->mode &&
7769 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7770
7771 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7772 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7773 curproxy->conf.file, curproxy->conf.line,
7774 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7775 target->conf.file, target->conf.line);
7776 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007777 } else {
7778 free((void *)rule->be.name);
7779 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007780 /* For each target of switching rules, we update
7781 * their tot_fe_maxconn, except if a previous rule point
7782 * on the same backend or on the default backend */
7783 if (rule->be.backend != curproxy->defbe.be) {
7784 struct switching_rule *swrule;
7785
7786 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7787 if (rule == swrule) {
7788 target->tot_fe_maxconn += curproxy->maxconn;
7789 break;
7790 }
7791 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7792 /* there is multiple ref of this backend */
7793 break;
7794 }
7795 }
7796 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007797 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007798 }
7799
Willy Tarreau64ab6072014-09-16 12:17:36 +02007800 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007801 list_for_each_entry(srule, &curproxy->server_rules, list) {
7802 struct server *target = findserver(curproxy, srule->srv.name);
7803
7804 if (!target) {
7805 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7806 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7807 cfgerr++;
7808 continue;
7809 }
7810 free((void *)srule->srv.name);
7811 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007812 }
7813
Emeric Brunb982a3d2010-01-04 15:45:53 +01007814 /* find the target table for 'stick' rules */
7815 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7816 struct proxy *target;
7817
Emeric Brun1d33b292010-01-04 15:47:17 +01007818 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7819 if (mrule->flags & STK_IS_STORE)
7820 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7821
Emeric Brunb982a3d2010-01-04 15:45:53 +01007822 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007823 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007824 else
7825 target = curproxy;
7826
7827 if (!target) {
7828 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7829 curproxy->id, mrule->table.name);
7830 cfgerr++;
7831 }
7832 else if (target->table.size == 0) {
7833 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7834 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7835 cfgerr++;
7836 }
Willy Tarreau12785782012-04-27 21:37:17 +02007837 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7838 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007839 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7840 cfgerr++;
7841 }
7842 else {
7843 free((void *)mrule->table.name);
7844 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007845 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007846 }
7847 }
7848
7849 /* find the target table for 'store response' rules */
7850 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7851 struct proxy *target;
7852
Emeric Brun1d33b292010-01-04 15:47:17 +01007853 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7854
Emeric Brunb982a3d2010-01-04 15:45:53 +01007855 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007856 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007857 else
7858 target = curproxy;
7859
7860 if (!target) {
7861 Alert("Proxy '%s': unable to find store table '%s'.\n",
7862 curproxy->id, mrule->table.name);
7863 cfgerr++;
7864 }
7865 else if (target->table.size == 0) {
7866 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7867 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7868 cfgerr++;
7869 }
Willy Tarreau12785782012-04-27 21:37:17 +02007870 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7871 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007872 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7873 cfgerr++;
7874 }
7875 else {
7876 free((void *)mrule->table.name);
7877 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007878 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007879 }
7880 }
7881
Christopher Faulete4e830d2017-09-18 14:51:41 +02007882 /* check validity for 'tcp-request' layer 4 rules */
7883 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
7884 err = NULL;
7885 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7886 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7887 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01007888 cfgerr++;
7889 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007890 }
7891
Christopher Faulete4e830d2017-09-18 14:51:41 +02007892 /* check validity for 'tcp-request' layer 5 rules */
7893 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
7894 err = NULL;
7895 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7896 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7897 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007898 cfgerr++;
7899 }
7900 }
7901
Christopher Faulete4e830d2017-09-18 14:51:41 +02007902 /* check validity for 'tcp-request' layer 6 rules */
7903 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
7904 err = NULL;
7905 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7906 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7907 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007908 cfgerr++;
7909 }
7910 }
7911
Christopher Faulete4e830d2017-09-18 14:51:41 +02007912 /* check validity for 'http-request' layer 7 rules */
7913 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
7914 err = NULL;
7915 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7916 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7917 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007918 cfgerr++;
7919 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007920 }
7921
Christopher Faulete4e830d2017-09-18 14:51:41 +02007922 /* check validity for 'http-response' layer 7 rules */
7923 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
7924 err = NULL;
7925 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7926 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7927 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02007928 cfgerr++;
7929 }
Willy Tarreau09448f72014-06-25 18:12:15 +02007930 }
7931
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007932 /* move any "block" rules at the beginning of the http-request rules */
7933 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7934 /* insert block_rules into http_req_rules at the beginning */
7935 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7936 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7937 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7938 curproxy->http_req_rules.n = curproxy->block_rules.n;
7939 LIST_INIT(&curproxy->block_rules);
7940 }
7941
Emeric Brun32da3c42010-09-23 18:39:19 +02007942 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007943 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007944
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007945 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02007946 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7947 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007948 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007949 break;
7950 }
7951 }
7952
7953 if (!curpeers) {
7954 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7955 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007956 free((void *)curproxy->table.peers.name);
7957 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007958 cfgerr++;
7959 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007960 else if (curpeers->state == PR_STSTOPPED) {
7961 /* silently disable this peers section */
7962 curproxy->table.peers.p = NULL;
7963 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007964 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007965 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7966 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007967 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007968 cfgerr++;
7969 }
7970 }
7971
Simon Horman9dc49962015-01-30 11:22:59 +09007972
7973 if (curproxy->email_alert.mailers.name) {
7974 struct mailers *curmailers = mailers;
7975
7976 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02007977 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09007978 break;
Simon Horman9dc49962015-01-30 11:22:59 +09007979 }
Simon Horman9dc49962015-01-30 11:22:59 +09007980 if (!curmailers) {
7981 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7982 curproxy->id, curproxy->email_alert.mailers.name);
7983 free_email_alert(curproxy);
7984 cfgerr++;
7985 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02007986 else {
7987 err = NULL;
7988 if (init_email_alert(curmailers, curproxy, &err)) {
7989 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7990 free(err);
7991 cfgerr++;
7992 }
7993 }
Simon Horman9dc49962015-01-30 11:22:59 +09007994 }
7995
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007996 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007997 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007998 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7999 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8000 "proxy", curproxy->id);
8001 cfgerr++;
8002 goto out_uri_auth_compat;
8003 }
8004
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008005 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008006 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008007 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008008 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008009
Willy Tarreau95fa4692010-02-01 13:05:50 +01008010 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8011 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008012
8013 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008014 uri_auth_compat_req[i++] = "realm";
8015 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8016 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008017
Willy Tarreau95fa4692010-02-01 13:05:50 +01008018 uri_auth_compat_req[i++] = "unless";
8019 uri_auth_compat_req[i++] = "{";
8020 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8021 uri_auth_compat_req[i++] = "}";
8022 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008023
Willy Tarreauff011f22011-01-06 17:51:27 +01008024 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8025 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008026 cfgerr++;
8027 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008028 }
8029
Willy Tarreauff011f22011-01-06 17:51:27 +01008030 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008031
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008032 if (curproxy->uri_auth->auth_realm) {
8033 free(curproxy->uri_auth->auth_realm);
8034 curproxy->uri_auth->auth_realm = NULL;
8035 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008036
8037 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008038 }
8039out_uri_auth_compat:
8040
Dragan Dosen43885c72015-10-01 13:18:13 +02008041 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008042 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008043 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8044 if (!curproxy->conf.logformat_sd_string) {
8045 /* set the default logformat_sd_string */
8046 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8047 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008048 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008049 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008050 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008051
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008052 /* compile the log format */
8053 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008054 if (curproxy->conf.logformat_string != default_http_log_format &&
8055 curproxy->conf.logformat_string != default_tcp_log_format &&
8056 curproxy->conf.logformat_string != clf_http_log_format)
8057 free(curproxy->conf.logformat_string);
8058 curproxy->conf.logformat_string = NULL;
8059 free(curproxy->conf.lfs_file);
8060 curproxy->conf.lfs_file = NULL;
8061 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008062
8063 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8064 free(curproxy->conf.logformat_sd_string);
8065 curproxy->conf.logformat_sd_string = NULL;
8066 free(curproxy->conf.lfsd_file);
8067 curproxy->conf.lfsd_file = NULL;
8068 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008069 }
8070
Willy Tarreau62a61232013-04-12 18:13:46 +02008071 if (curproxy->conf.logformat_string) {
8072 curproxy->conf.args.ctx = ARGC_LOG;
8073 curproxy->conf.args.file = curproxy->conf.lfs_file;
8074 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008075 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008076 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008077 SMP_VAL_FE_LOG_END, &err)) {
8078 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8079 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8080 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008081 cfgerr++;
8082 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008083 curproxy->conf.args.file = NULL;
8084 curproxy->conf.args.line = 0;
8085 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008086
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008087 if (curproxy->conf.logformat_sd_string) {
8088 curproxy->conf.args.ctx = ARGC_LOGSD;
8089 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8090 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008091 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008092 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 +01008093 SMP_VAL_FE_LOG_END, &err)) {
8094 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8095 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8096 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008097 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008098 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8099 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8100 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8101 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008102 cfgerr++;
8103 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008104 curproxy->conf.args.file = NULL;
8105 curproxy->conf.args.line = 0;
8106 }
8107
Willy Tarreau62a61232013-04-12 18:13:46 +02008108 if (curproxy->conf.uniqueid_format_string) {
8109 curproxy->conf.args.ctx = ARGC_UIF;
8110 curproxy->conf.args.file = curproxy->conf.uif_file;
8111 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008112 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008113 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 +01008114 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8115 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8116 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8117 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008118 cfgerr++;
8119 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008120 curproxy->conf.args.file = NULL;
8121 curproxy->conf.args.line = 0;
8122 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008123
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008124 /* only now we can check if some args remain unresolved.
8125 * This must be done after the users and groups resolution.
8126 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008127 cfgerr += smp_resolve_args(curproxy);
8128 if (!cfgerr)
8129 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008130
Willy Tarreau2738a142006-07-08 17:28:09 +02008131 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008132 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008133 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008134 (!curproxy->timeout.connect ||
8135 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008136 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008137 " | While not properly invalid, you will certainly encounter various problems\n"
8138 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008139 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008140 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008141 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008142 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008143
Willy Tarreau1fa31262007-12-03 00:36:16 +01008144 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8145 * We must still support older configurations, so let's find out whether those
8146 * parameters have been set or must be copied from contimeouts.
8147 */
8148 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008149 if (!curproxy->timeout.tarpit ||
8150 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008151 /* tarpit timeout not set. We search in the following order:
8152 * default.tarpit, curr.connect, default.connect.
8153 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008154 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008155 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008156 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008157 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008158 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008159 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008160 }
8161 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008162 (!curproxy->timeout.queue ||
8163 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008164 /* queue timeout not set. We search in the following order:
8165 * default.queue, curr.connect, default.connect.
8166 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008167 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008168 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008169 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008170 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008171 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008172 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008173 }
8174 }
8175
Willy Tarreau1620ec32011-08-06 17:05:02 +02008176 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008177 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008178 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008179 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008180 }
8181
Willy Tarreau215663d2014-06-13 18:30:23 +02008182 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8183 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8184 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8185 proxy_type_str(curproxy), curproxy->id);
8186 err_code |= ERR_WARN;
8187 }
8188
Willy Tarreau193b8c62012-11-22 00:17:38 +01008189 /* ensure that cookie capture length is not too large */
8190 if (curproxy->capture_len >= global.tune.cookie_len) {
8191 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8192 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8193 err_code |= ERR_WARN;
8194 curproxy->capture_len = global.tune.cookie_len - 1;
8195 }
8196
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008197 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008198 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008199 curproxy->req_cap_pool = create_pool("ptrcap",
8200 curproxy->nb_req_cap * sizeof(char *),
8201 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008202 }
8203
8204 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008205 curproxy->rsp_cap_pool = create_pool("ptrcap",
8206 curproxy->nb_rsp_cap * sizeof(char *),
8207 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008208 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008209
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008210 switch (curproxy->load_server_state_from_file) {
8211 case PR_SRV_STATE_FILE_UNSPEC:
8212 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8213 break;
8214 case PR_SRV_STATE_FILE_GLOBAL:
8215 if (!global.server_state_file) {
8216 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",
8217 curproxy->id);
8218 err_code |= ERR_WARN;
8219 }
8220 break;
8221 }
8222
Willy Tarreaubaaee002006-06-26 02:48:02 +02008223 /* first, we will invert the servers list order */
8224 newsrv = NULL;
8225 while (curproxy->srv) {
8226 struct server *next;
8227
8228 next = curproxy->srv->next;
8229 curproxy->srv->next = newsrv;
8230 newsrv = curproxy->srv;
8231 if (!next)
8232 break;
8233 curproxy->srv = next;
8234 }
8235
Willy Tarreau17edc812014-01-03 12:14:34 +01008236 /* Check that no server name conflicts. This causes trouble in the stats.
8237 * We only emit a warning for the first conflict affecting each server,
8238 * in order to avoid combinatory explosion if all servers have the same
8239 * name. We do that only for servers which do not have an explicit ID,
8240 * because these IDs were made also for distinguishing them and we don't
8241 * want to annoy people who correctly manage them.
8242 */
8243 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8244 struct server *other_srv;
8245
8246 if (newsrv->puid)
8247 continue;
8248
8249 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8250 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8251 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8252 newsrv->conf.file, newsrv->conf.line,
8253 proxy_type_str(curproxy), curproxy->id,
8254 newsrv->id, other_srv->conf.line);
8255 break;
8256 }
8257 }
8258 }
8259
Willy Tarreaudd701652010-05-25 23:03:02 +02008260 /* assign automatic UIDs to servers which don't have one yet */
8261 next_id = 1;
8262 newsrv = curproxy->srv;
8263 while (newsrv != NULL) {
8264 if (!newsrv->puid) {
8265 /* server ID not set, use automatic numbering with first
8266 * spare entry starting with next_svid.
8267 */
8268 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8269 newsrv->conf.id.key = newsrv->puid = next_id;
8270 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8271 }
8272 next_id++;
8273 newsrv = newsrv->next;
8274 }
8275
Willy Tarreau20697042007-11-15 23:26:18 +01008276 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008277 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008278
Willy Tarreau62c3be22012-01-20 13:12:32 +01008279 /*
8280 * If this server supports a maxconn parameter, it needs a dedicated
8281 * tasks to fill the emptied slots when a connection leaves.
8282 * Also, resolve deferred tracking dependency if needed.
8283 */
8284 newsrv = curproxy->srv;
8285 while (newsrv != NULL) {
8286 if (newsrv->minconn > newsrv->maxconn) {
8287 /* Only 'minconn' was specified, or it was higher than or equal
8288 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8289 * this will avoid further useless expensive computations.
8290 */
8291 newsrv->maxconn = newsrv->minconn;
8292 } else if (newsrv->maxconn && !newsrv->minconn) {
8293 /* minconn was not specified, so we set it to maxconn */
8294 newsrv->minconn = newsrv->maxconn;
8295 }
8296
Willy Tarreau17d45382016-12-22 21:16:08 +01008297 /* this will also properly set the transport layer for prod and checks */
8298 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8299 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8300 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8301 }
Emeric Brun94324a42012-10-11 14:00:19 +02008302
Willy Tarreau2f075e92013-12-03 11:11:34 +01008303 /* set the check type on the server */
8304 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8305
Willy Tarreau62c3be22012-01-20 13:12:32 +01008306 if (newsrv->trackit) {
8307 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008308 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008309 char *pname, *sname;
8310
8311 pname = newsrv->trackit;
8312 sname = strrchr(pname, '/');
8313
8314 if (sname)
8315 *sname++ = '\0';
8316 else {
8317 sname = pname;
8318 pname = NULL;
8319 }
8320
8321 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008322 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008323 if (!px) {
8324 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8325 proxy_type_str(curproxy), curproxy->id,
8326 newsrv->id, pname);
8327 cfgerr++;
8328 goto next_srv;
8329 }
8330 } else
8331 px = curproxy;
8332
8333 srv = findserver(px, sname);
8334 if (!srv) {
8335 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8336 proxy_type_str(curproxy), curproxy->id,
8337 newsrv->id, sname);
8338 cfgerr++;
8339 goto next_srv;
8340 }
8341
Willy Tarreau32091232014-05-16 13:52:00 +02008342 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8343 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8344 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008345 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008346 "tracking as it does not have any check nor agent enabled.\n",
8347 proxy_type_str(curproxy), curproxy->id,
8348 newsrv->id, px->id, srv->id);
8349 cfgerr++;
8350 goto next_srv;
8351 }
8352
8353 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8354
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008355 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008356 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8357 "belongs to a tracking chain looping back to %s/%s.\n",
8358 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008359 newsrv->id, px->id, srv->id, px->id,
8360 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008361 cfgerr++;
8362 goto next_srv;
8363 }
8364
8365 if (curproxy != px &&
8366 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8367 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8368 "tracking: disable-on-404 option inconsistency.\n",
8369 proxy_type_str(curproxy), curproxy->id,
8370 newsrv->id, px->id, srv->id);
8371 cfgerr++;
8372 goto next_srv;
8373 }
8374
Willy Tarreau62c3be22012-01-20 13:12:32 +01008375 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008376 newsrv->tracknext = srv->trackers;
8377 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008378
8379 free(newsrv->trackit);
8380 newsrv->trackit = NULL;
8381 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008382
Willy Tarreau62c3be22012-01-20 13:12:32 +01008383 next_srv:
8384 newsrv = newsrv->next;
8385 }
8386
Olivier Houchard4e694042017-03-14 20:01:29 +01008387 /*
8388 * Try to generate dynamic cookies for servers now.
8389 * It couldn't be done earlier, since at the time we parsed
8390 * the server line, we may not have known yet that we
8391 * should use dynamic cookies, or the secret key may not
8392 * have been provided yet.
8393 */
8394 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8395 newsrv = curproxy->srv;
8396 while (newsrv != NULL) {
8397 srv_set_dyncookie(newsrv);
8398 newsrv = newsrv->next;
8399 }
8400
8401 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008402 /* We have to initialize the server lookup mechanism depending
8403 * on what LB algorithm was choosen.
8404 */
8405
8406 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8407 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8408 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008409 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8410 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8411 init_server_map(curproxy);
8412 } else {
8413 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8414 fwrr_init_server_groups(curproxy);
8415 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008416 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008417
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008418 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008419 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8420 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8421 fwlc_init_server_tree(curproxy);
8422 } else {
8423 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8424 fas_init_server_tree(curproxy);
8425 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008426 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008427
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008428 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008429 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8430 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8431 chash_init_server_tree(curproxy);
8432 } else {
8433 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8434 init_server_map(curproxy);
8435 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008436 break;
8437 }
Christopher Faulet5b517552017-06-09 14:17:53 +02008438 SPIN_INIT(&curproxy->lbprm.lock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02008439
8440 if (curproxy->options & PR_O_LOGASAP)
8441 curproxy->to_log &= ~LW_BYTES;
8442
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008443 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008444 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8445 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008446 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8447 proxy_type_str(curproxy), curproxy->id);
8448 err_code |= ERR_WARN;
8449 }
8450
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008451 if (curproxy->mode != PR_MODE_HTTP) {
8452 int optnum;
8453
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008454 if (curproxy->uri_auth) {
8455 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8456 proxy_type_str(curproxy), curproxy->id);
8457 err_code |= ERR_WARN;
8458 curproxy->uri_auth = NULL;
8459 }
8460
Willy Tarreaude7dc882017-03-10 11:49:21 +01008461 if (curproxy->capture_name) {
8462 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8463 proxy_type_str(curproxy), curproxy->id);
8464 err_code |= ERR_WARN;
8465 }
8466
8467 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8468 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8469 proxy_type_str(curproxy), curproxy->id);
8470 err_code |= ERR_WARN;
8471 }
8472
8473 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8474 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8475 proxy_type_str(curproxy), curproxy->id);
8476 err_code |= ERR_WARN;
8477 }
8478
8479 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8480 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8481 proxy_type_str(curproxy), curproxy->id);
8482 err_code |= ERR_WARN;
8483 }
8484
8485 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8486 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8487 proxy_type_str(curproxy), curproxy->id);
8488 err_code |= ERR_WARN;
8489 }
8490
Willy Tarreau87cf5142011-08-19 22:57:24 +02008491 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008492 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8493 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8494 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008495 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008496 }
8497
8498 if (curproxy->options & PR_O_ORGTO) {
8499 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8500 "originalto", proxy_type_str(curproxy), curproxy->id);
8501 err_code |= ERR_WARN;
8502 curproxy->options &= ~PR_O_ORGTO;
8503 }
8504
8505 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8506 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8507 (curproxy->cap & cfg_opts[optnum].cap) &&
8508 (curproxy->options & cfg_opts[optnum].val)) {
8509 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8510 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8511 err_code |= ERR_WARN;
8512 curproxy->options &= ~cfg_opts[optnum].val;
8513 }
8514 }
8515
8516 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8517 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8518 (curproxy->cap & cfg_opts2[optnum].cap) &&
8519 (curproxy->options2 & cfg_opts2[optnum].val)) {
8520 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8521 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8522 err_code |= ERR_WARN;
8523 curproxy->options2 &= ~cfg_opts2[optnum].val;
8524 }
8525 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008526
Willy Tarreau29fbe512015-08-20 19:35:14 +02008527#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008528 if (curproxy->conn_src.bind_hdr_occ) {
8529 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008530 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008531 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008532 err_code |= ERR_WARN;
8533 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008534#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008535 }
8536
Willy Tarreaubaaee002006-06-26 02:48:02 +02008537 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008538 * ensure that we're not cross-dressing a TCP server into HTTP.
8539 */
8540 newsrv = curproxy->srv;
8541 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008542 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008543 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8544 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008545 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008546 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008547
Willy Tarreau0cec3312011-10-31 13:49:26 +01008548 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8549 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8550 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8551 err_code |= ERR_WARN;
8552 }
8553
Willy Tarreauc93cd162014-05-13 15:54:22 +02008554 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008555 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8556 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8557 err_code |= ERR_WARN;
8558 }
8559
Willy Tarreau29fbe512015-08-20 19:35:14 +02008560#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008561 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8562 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008563 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 +01008564 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008565 err_code |= ERR_WARN;
8566 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008567#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008568
8569 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8570 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8571 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8572 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8573 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8574 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",
8575 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8576 err_code |= ERR_WARN;
8577 }
8578
8579
8580 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8581 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",
8582 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8583 err_code |= ERR_WARN;
8584 }
8585 }
8586
Willy Tarreau21d2af32008-02-14 20:25:24 +01008587 newsrv = newsrv->next;
8588 }
8589
Willy Tarreaue42bd962014-09-16 16:21:19 +02008590 /* check if we have a frontend with "tcp-request content" looking at L7
8591 * with no inspect-delay
8592 */
8593 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008594 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8595 if (arule->action == ACT_TCP_CAPTURE &&
8596 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008597 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008598 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8599 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008600 break;
8601 }
8602
Christopher Faulete4e830d2017-09-18 14:51:41 +02008603 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008604 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8605 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8606 " This means that these rules will randomly find their contents. This can be fixed by"
8607 " setting the tcp-request inspect-delay.\n",
8608 proxy_type_str(curproxy), curproxy->id);
8609 err_code |= ERR_WARN;
8610 }
8611 }
8612
Christopher Fauletd7c91962015-04-30 11:48:27 +02008613 /* Check filter configuration, if any */
8614 cfgerr += flt_check(curproxy);
8615
Willy Tarreauc1a21672009-08-16 22:37:44 +02008616 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008617 if (!curproxy->accept)
8618 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008619
Willy Tarreauc1a21672009-08-16 22:37:44 +02008620 if (curproxy->tcp_req.inspect_delay ||
8621 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008622 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008623
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008624 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008625 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008626 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008627 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008628
8629 /* both TCP and HTTP must check switching rules */
8630 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008631
8632 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008633 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008634 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8635 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 +01008636 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008637 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8638 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008639 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008640 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008641 }
8642
8643 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008644 if (curproxy->tcp_req.inspect_delay ||
8645 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8646 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8647
Emeric Brun97679e72010-09-23 17:56:44 +02008648 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8649 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8650
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008651 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008652 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008653 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008654 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008655
8656 /* If the backend does requires RDP cookie persistence, we have to
8657 * enable the corresponding analyser.
8658 */
8659 if (curproxy->options2 & PR_O2_RDPC_PRST)
8660 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008661
8662 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008663 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008664 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8665 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 +01008666 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008667 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8668 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008669 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008670 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008671 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008672 }
8673
8674 /***********************************************************/
8675 /* At this point, target names have already been resolved. */
8676 /***********************************************************/
8677
8678 /* Check multi-process mode compatibility */
8679
8680 if (global.nbproc > 1 && global.stats_fe) {
8681 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8682 unsigned long mask;
8683
8684 mask = nbits(global.nbproc);
8685 if (global.stats_fe->bind_proc)
8686 mask &= global.stats_fe->bind_proc;
8687
8688 if (bind_conf->bind_proc)
8689 mask &= bind_conf->bind_proc;
8690
8691 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008692 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008693 break;
8694 }
8695 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8696 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");
8697 }
8698 }
8699
8700 /* Make each frontend inherit bind-process from its listeners when not specified. */
8701 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8702 if (curproxy->bind_proc)
8703 continue;
8704
8705 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8706 unsigned long mask;
8707
Willy Tarreaue428b082015-05-04 21:57:58 +02008708 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008709 curproxy->bind_proc |= mask;
8710 }
8711
8712 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008713 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008714 }
8715
8716 if (global.stats_fe) {
8717 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8718 unsigned long mask;
8719
Cyril Bonté06181952016-02-24 00:14:54 +01008720 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008721 global.stats_fe->bind_proc |= mask;
8722 }
8723 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008724 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008725 }
8726
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008727 /* propagate bindings from frontends to backends. Don't do it if there
8728 * are any fatal errors as we must not call it with unresolved proxies.
8729 */
8730 if (!cfgerr) {
8731 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8732 if (curproxy->cap & PR_CAP_FE)
8733 propagate_processes(curproxy, NULL);
8734 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008735 }
8736
8737 /* Bind each unbound backend to all processes when not specified. */
8738 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8739 if (curproxy->bind_proc)
8740 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008741 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008742 }
8743
8744 /*******************************************************/
8745 /* At this step, all proxies have a non-null bind_proc */
8746 /*******************************************************/
8747
8748 /* perform the final checks before creating tasks */
8749
8750 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8751 struct listener *listener;
8752 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008753
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008754 /* Configure SSL for each bind line.
8755 * Note: if configuration fails at some point, the ->ctx member
8756 * remains NULL so that listeners can later detach.
8757 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008758 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008759 if (bind_conf->xprt->prepare_bind_conf &&
8760 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008761 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008762 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008763
Willy Tarreaue6b98942007-10-29 01:09:36 +01008764 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008765 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008766 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008767 int nbproc;
8768
8769 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008770 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008771 nbits(global.nbproc));
8772
8773 if (!nbproc) /* no intersection between listener and frontend */
8774 nbproc = 1;
8775
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008776 if (!listener->luid) {
8777 /* listener ID not set, use automatic numbering with first
8778 * spare entry starting with next_luid.
8779 */
8780 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8781 listener->conf.id.key = listener->luid = next_id;
8782 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008783 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008784 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008785
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008786 /* enable separate counters */
8787 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008788 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008789 if (!listener->name)
8790 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008791 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008792
Willy Tarreaue6b98942007-10-29 01:09:36 +01008793 if (curproxy->options & PR_O_TCP_NOLING)
8794 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008795 if (!listener->maxconn)
8796 listener->maxconn = curproxy->maxconn;
8797 if (!listener->backlog)
8798 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008799 if (!listener->maxaccept)
8800 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8801
8802 /* we want to have an optimal behaviour on single process mode to
8803 * maximize the work at once, but in multi-process we want to keep
8804 * some fairness between processes, so we target half of the max
8805 * number of events to be balanced over all the processes the proxy
8806 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8807 * used to disable the limit.
8808 */
8809 if (listener->maxaccept > 0) {
8810 if (nbproc > 1)
8811 listener->maxaccept = (listener->maxaccept + 1) / 2;
8812 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8813 }
8814
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008815 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008816 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008817 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008818
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008819 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008820 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008821
Willy Tarreau620408f2016-10-21 16:37:51 +02008822 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8823 listener->options |= LI_O_TCP_L5_RULES;
8824
Willy Tarreaude3041d2010-05-31 10:56:17 +02008825 if (curproxy->mon_mask.s_addr)
8826 listener->options |= LI_O_CHK_MONNET;
8827
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008828 /* smart accept mode is automatic in HTTP mode */
8829 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008830 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008831 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8832 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008833 }
8834
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008835 /* Release unused SSL configs */
8836 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008837 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8838 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008839 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008840
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008841 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008842 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008843 int count, maxproc = 0;
8844
8845 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008846 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008847 if (count > maxproc)
8848 maxproc = count;
8849 }
8850 /* backends have 0, frontends have 1 or more */
8851 if (maxproc != 1)
8852 Warning("Proxy '%s': in multi-process mode, stats will be"
8853 " limited to process assigned to the current request.\n",
8854 curproxy->id);
8855
Willy Tarreau102df612014-05-07 23:56:38 +02008856 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8857 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8858 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008859 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008860 }
Willy Tarreau102df612014-05-07 23:56:38 +02008861 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8862 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8863 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008864 }
8865 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008866
8867 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02008868 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02008869 if (curproxy->task) {
8870 curproxy->task->context = curproxy;
8871 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02008872 } else {
8873 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8874 curproxy->id);
8875 cfgerr++;
8876 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008877 }
8878
Willy Tarreaufbb78422011-06-05 15:38:35 +02008879 /* automatically compute fullconn if not set. We must not do it in the
8880 * loop above because cross-references are not yet fully resolved.
8881 */
8882 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8883 /* If <fullconn> is not set, let's set it to 10% of the sum of
8884 * the possible incoming frontend's maxconns.
8885 */
8886 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008887 /* we have the sum of the maxconns in <total>. We only
8888 * keep 10% of that sum to set the default fullconn, with
8889 * a hard minimum of 1 (to avoid a divide by zero).
8890 */
Emeric Brun3f783572017-01-12 11:21:28 +01008891 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008892 if (!curproxy->fullconn)
8893 curproxy->fullconn = 1;
8894 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008895 }
8896
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008897 /*
8898 * Recount currently required checks.
8899 */
8900
8901 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8902 int optnum;
8903
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008904 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8905 if (curproxy->options & cfg_opts[optnum].val)
8906 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008907
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008908 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8909 if (curproxy->options2 & cfg_opts2[optnum].val)
8910 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008911 }
8912
Willy Tarreau0fca4832015-05-01 19:12:05 +02008913 /* compute the required process bindings for the peers */
8914 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8915 if (curproxy->table.peers.p)
8916 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8917
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008918 if (cfg_peers) {
8919 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02008920 struct peer *p, *pb;
8921
Willy Tarreau1e273012015-05-01 19:15:17 +02008922 /* Remove all peers sections which don't have a valid listener,
8923 * which are not used by any table, or which are bound to more
8924 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008925 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008926 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02008927 while (*last) {
8928 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008929
8930 if (curpeers->state == PR_STSTOPPED) {
8931 /* the "disabled" keyword was present */
8932 if (curpeers->peers_fe)
8933 stop_proxy(curpeers->peers_fe);
8934 curpeers->peers_fe = NULL;
8935 }
8936 else if (!curpeers->peers_fe) {
8937 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8938 curpeers->id, localpeer);
8939 }
David Carliere6c39412015-07-02 07:00:17 +00008940 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008941 /* either it's totally stopped or too much used */
8942 if (curpeers->peers_fe->bind_proc) {
8943 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008944 "running in different processes (%d different ones). "
8945 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008946 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008947 cfgerr++;
8948 }
8949 stop_proxy(curpeers->peers_fe);
8950 curpeers->peers_fe = NULL;
8951 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008952 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008953 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008954 last = &curpeers->next;
8955 continue;
8956 }
8957
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008958 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008959 p = curpeers->remote;
8960 while (p) {
8961 pb = p->next;
8962 free(p->id);
8963 free(p);
8964 p = pb;
8965 }
8966
8967 /* Destroy and unlink this curpeers section.
8968 * Note: curpeers is backed up into *last.
8969 */
8970 free(curpeers->id);
8971 curpeers = curpeers->next;
8972 free(*last);
8973 *last = curpeers;
8974 }
8975 }
8976
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008977 /* initialize stick-tables on backend capable proxies. This must not
8978 * be done earlier because the data size may be discovered while parsing
8979 * other proxies.
8980 */
8981 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8982 if (curproxy->state == PR_STSTOPPED)
8983 continue;
8984
8985 if (!stktable_init(&curproxy->table)) {
8986 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8987 cfgerr++;
8988 }
8989 }
8990
Simon Horman0d16a402015-01-30 11:22:58 +09008991 if (mailers) {
8992 struct mailers *curmailers = mailers, **last;
8993 struct mailer *m, *mb;
8994
8995 /* Remove all mailers sections which don't have a valid listener.
8996 * This can happen when a mailers section is never referenced.
8997 */
8998 last = &mailers;
8999 while (*last) {
9000 curmailers = *last;
9001 if (curmailers->users) {
9002 last = &curmailers->next;
9003 continue;
9004 }
9005
9006 Warning("Removing incomplete section 'mailers %s'.\n",
9007 curmailers->id);
9008
9009 m = curmailers->mailer_list;
9010 while (m) {
9011 mb = m->next;
9012 free(m->id);
9013 free(m);
9014 m = mb;
9015 }
9016
9017 /* Destroy and unlink this curmailers section.
9018 * Note: curmailers is backed up into *last.
9019 */
9020 free(curmailers->id);
9021 curmailers = curmailers->next;
9022 free(*last);
9023 *last = curmailers;
9024 }
9025 }
9026
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009027 /* Update server_state_file_name to backend name if backend is supposed to use
9028 * a server-state file locally defined and none has been provided */
9029 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9030 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9031 curproxy->server_state_file_name == NULL)
9032 curproxy->server_state_file_name = strdup(curproxy->id);
9033 }
9034
Willy Tarreau34eb6712011-10-24 18:15:04 +02009035 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009036 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009037 MEM_F_SHARED);
9038
William Lallemand48b4bb42017-10-23 14:36:34 +02009039 list_for_each_entry(postparser, &postparsers, list) {
9040 if (postparser->func)
9041 cfgerr += postparser->func();
9042 }
9043
Willy Tarreaubb925012009-07-23 13:36:36 +02009044 if (cfgerr > 0)
9045 err_code |= ERR_ALERT | ERR_FATAL;
9046 out:
9047 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009048}
9049
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009050/*
9051 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9052 * parsing sessions.
9053 */
9054void cfg_register_keywords(struct cfg_kw_list *kwl)
9055{
9056 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9057}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009058
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009059/*
9060 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9061 */
9062void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9063{
9064 LIST_DEL(&kwl->list);
9065 LIST_INIT(&kwl->list);
9066}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009067
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009068/* this function register new section in the haproxy configuration file.
9069 * <section_name> is the name of this new section and <section_parser>
9070 * is the called parser. If two section declaration have the same name,
9071 * only the first declared is used.
9072 */
9073int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009074 int (*section_parser)(const char *, int, char **, int),
9075 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009076{
9077 struct cfg_section *cs;
9078
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009079 list_for_each_entry(cs, &sections, list) {
9080 if (strcmp(cs->section_name, section_name) == 0) {
9081 Alert("register section '%s': already registered.\n", section_name);
9082 return 0;
9083 }
9084 }
9085
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009086 cs = calloc(1, sizeof(*cs));
9087 if (!cs) {
9088 Alert("register section '%s': out of memory.\n", section_name);
9089 return 0;
9090 }
9091
9092 cs->section_name = section_name;
9093 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009094 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009095
9096 LIST_ADDQ(&sections, &cs->list);
9097
9098 return 1;
9099}
9100
William Lallemand48b4bb42017-10-23 14:36:34 +02009101/* this function register a new function which will be called once the haproxy
9102 * configuration file has been parsed. It's useful to check dependencies
9103 * between sections or to resolve items once everything is parsed.
9104 */
9105int cfg_register_postparser(char *name, int (*func)())
9106{
9107 struct cfg_postparser *cp;
9108
9109 cp = calloc(1, sizeof(*cp));
9110 if (!cp) {
9111 Alert("register postparser '%s': out of memory.\n", name);
9112 return 0;
9113 }
9114 cp->name = name;
9115 cp->func = func;
9116
9117 LIST_ADDQ(&postparsers, &cp->list);
9118
9119 return 1;
9120}
9121
Willy Tarreaubaaee002006-06-26 02:48:02 +02009122/*
David Carlier845efb52015-09-25 11:49:18 +01009123 * free all config section entries
9124 */
9125void cfg_unregister_sections(void)
9126{
9127 struct cfg_section *cs, *ics;
9128
9129 list_for_each_entry_safe(cs, ics, &sections, list) {
9130 LIST_DEL(&cs->list);
9131 free(cs);
9132 }
9133}
9134
Christopher Faulet7110b402016-10-26 11:09:44 +02009135void cfg_backup_sections(struct list *backup_sections)
9136{
9137 struct cfg_section *cs, *ics;
9138
9139 list_for_each_entry_safe(cs, ics, &sections, list) {
9140 LIST_DEL(&cs->list);
9141 LIST_ADDQ(backup_sections, &cs->list);
9142 }
9143}
9144
9145void cfg_restore_sections(struct list *backup_sections)
9146{
9147 struct cfg_section *cs, *ics;
9148
9149 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9150 LIST_DEL(&cs->list);
9151 LIST_ADDQ(&sections, &cs->list);
9152 }
9153}
9154
Willy Tarreau659fbf02016-05-26 17:55:28 +02009155__attribute__((constructor))
9156static void cfgparse_init(void)
9157{
9158 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009159 cfg_register_section("listen", cfg_parse_listen, NULL);
9160 cfg_register_section("frontend", cfg_parse_listen, NULL);
9161 cfg_register_section("backend", cfg_parse_listen, NULL);
9162 cfg_register_section("defaults", cfg_parse_listen, NULL);
9163 cfg_register_section("global", cfg_parse_global, NULL);
9164 cfg_register_section("userlist", cfg_parse_users, NULL);
9165 cfg_register_section("peers", cfg_parse_peers, NULL);
9166 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9167 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9168 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009169}
9170
David Carlier845efb52015-09-25 11:49:18 +01009171/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009172 * Local variables:
9173 * c-indent-level: 8
9174 * c-basic-offset: 8
9175 * End:
9176 */