blob: d693bfbf568c9b45de23a9b6d38f282480823bfc [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);
Christopher Fauletb2812a62017-10-04 16:17:58 +02002185 SPIN_INIT(&curr_resolvers->lock);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002186 }
2187 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2188 struct sockaddr_storage *sk;
2189 int port1, port2;
2190 struct protocol *proto;
2191
2192 if (!*args[2]) {
2193 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2194 file, linenum, args[0]);
2195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
2197 }
2198
2199 err = invalid_char(args[1]);
2200 if (err) {
2201 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2202 file, linenum, *err, args[1]);
2203 err_code |= ERR_ALERT | ERR_FATAL;
2204 goto out;
2205 }
2206
Christopher Faulet67957bd2017-09-27 11:00:59 +02002207 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002208 /* Error if two resolvers owns the same name */
2209 if (strcmp(newnameserver->id, args[1]) == 0) {
2210 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2211 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 }
2214 }
2215
Vincent Bernat02779b62016-04-03 13:48:43 +02002216 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2218 err_code |= ERR_ALERT | ERR_ABORT;
2219 goto out;
2220 }
2221
2222 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002223 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002224 newnameserver->resolvers = curr_resolvers;
2225 newnameserver->conf.file = strdup(file);
2226 newnameserver->conf.line = linenum;
2227 newnameserver->id = strdup(args[1]);
2228
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002229 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002230 if (!sk) {
2231 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
2234 }
2235
2236 proto = protocol_by_family(sk->ss_family);
2237 if (!proto || !proto->connect) {
2238 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2239 file, linenum, args[0], args[1]);
2240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
2242 }
2243
2244 if (port1 != port2) {
2245 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2246 file, linenum, args[0], args[1], args[2]);
2247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
2249 }
2250
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002251 if (!port1 && !port2) {
2252 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2253 file, linenum, args[0], args[1]);
2254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
2256 }
2257
Baptiste Assmann325137d2015-04-13 23:40:55 +02002258 newnameserver->addr = *sk;
2259 }
2260 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2261 const char *res;
2262 unsigned int time;
2263
2264 if (!*args[2]) {
2265 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2266 file, linenum, args[0]);
2267 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
2270 }
2271 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2272 if (res) {
2273 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2274 file, linenum, *res, args[0]);
2275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
2277 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002278 if (strcmp(args[1], "nx") == 0)
2279 curr_resolvers->hold.nx = time;
2280 else if (strcmp(args[1], "other") == 0)
2281 curr_resolvers->hold.other = time;
2282 else if (strcmp(args[1], "refused") == 0)
2283 curr_resolvers->hold.refused = time;
2284 else if (strcmp(args[1], "timeout") == 0)
2285 curr_resolvers->hold.timeout = time;
2286 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002287 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002288 else if (strcmp(args[1], "obsolete") == 0)
2289 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002290 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002291 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002292 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
2295 }
2296
2297 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002298 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002299 int i = 0;
2300
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002301 if (!*args[1]) {
2302 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2303 file, linenum, args[0]);
2304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
2306 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002307
2308 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002309 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2310 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2311 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
2314 }
2315
2316 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002317 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002318 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002319 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2320 file, linenum, args[0]);
2321 err_code |= ERR_WARN;
2322 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002323 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002324 else if (strcmp(args[0], "resolve_retries") == 0) {
2325 if (!*args[1]) {
2326 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2327 file, linenum, args[0]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331 curr_resolvers->resolve_retries = atoi(args[1]);
2332 }
2333 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002334 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002335 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002336 file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002340 else if (strcmp(args[1], "retry") == 0 ||
2341 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002342 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002343 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002344
2345 if (!*args[2]) {
2346 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2347 file, linenum, args[0], args[1]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002351 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002352 if (res) {
2353 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2354 file, linenum, *res, args[0], args[1]);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002358 if (args[1][2] == 't')
2359 curr_resolvers->timeout.retry = tout;
2360 else
2361 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002362 }
2363 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002364 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002365 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002369 } /* neither "nameserver" nor "resolvers" */
2370 else if (*args[0] != 0) {
2371 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
2374 }
2375
2376 out:
2377 free(errmsg);
2378 return err_code;
2379}
Simon Horman0d16a402015-01-30 11:22:58 +09002380
2381/*
William Lallemand51097192015-04-14 16:35:22 +02002382 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002383 * Returns the error code, 0 if OK, or any combination of :
2384 * - ERR_ABORT: must abort ASAP
2385 * - ERR_FATAL: we can continue parsing but not start the service
2386 * - ERR_WARN: a warning has been emitted
2387 * - ERR_ALERT: an alert has been emitted
2388 * Only the two first ones can stop processing, the two others are just
2389 * indicators.
2390 */
2391int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2392{
2393 static struct mailers *curmailers = NULL;
2394 struct mailer *newmailer = NULL;
2395 const char *err;
2396 int err_code = 0;
2397 char *errmsg = NULL;
2398
2399 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2400 if (!*args[1]) {
2401 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2402 err_code |= ERR_ALERT | ERR_ABORT;
2403 goto out;
2404 }
2405
2406 err = invalid_char(args[1]);
2407 if (err) {
2408 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2409 file, linenum, *err, args[0], args[1]);
2410 err_code |= ERR_ALERT | ERR_ABORT;
2411 goto out;
2412 }
2413
2414 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2415 /*
2416 * If there are two proxies with the same name only following
2417 * combinations are allowed:
2418 */
2419 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002420 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 +09002421 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002423 }
2424 }
2425
Vincent Bernat02779b62016-04-03 13:48:43 +02002426 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002427 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2428 err_code |= ERR_ALERT | ERR_ABORT;
2429 goto out;
2430 }
2431
2432 curmailers->next = mailers;
2433 mailers = curmailers;
2434 curmailers->conf.file = strdup(file);
2435 curmailers->conf.line = linenum;
2436 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002437 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2438 * But need enough time so that timeouts don't occur
2439 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002440 }
2441 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2442 struct sockaddr_storage *sk;
2443 int port1, port2;
2444 struct protocol *proto;
2445
2446 if (!*args[2]) {
2447 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2448 file, linenum, args[0]);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452
2453 err = invalid_char(args[1]);
2454 if (err) {
2455 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2456 file, linenum, *err, args[1]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460
Vincent Bernat02779b62016-04-03 13:48:43 +02002461 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002462 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2463 err_code |= ERR_ALERT | ERR_ABORT;
2464 goto out;
2465 }
2466
2467 /* the mailers are linked backwards first */
2468 curmailers->count++;
2469 newmailer->next = curmailers->mailer_list;
2470 curmailers->mailer_list = newmailer;
2471 newmailer->mailers = curmailers;
2472 newmailer->conf.file = strdup(file);
2473 newmailer->conf.line = linenum;
2474
2475 newmailer->id = strdup(args[1]);
2476
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002477 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002478 if (!sk) {
2479 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
2482 }
2483
2484 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002485 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2486 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002487 file, linenum, args[0], args[1]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491
2492 if (port1 != port2) {
2493 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2494 file, linenum, args[0], args[1], args[2]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498
2499 if (!port1) {
2500 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2501 file, linenum, args[0], args[1], args[2]);
2502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
2505
2506 newmailer->addr = *sk;
2507 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002508 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002509 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002510 }
2511 else if (strcmp(args[0], "timeout") == 0) {
2512 if (!*args[1]) {
2513 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2514 file, linenum, args[0]);
2515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
2517 }
2518 else if (strcmp(args[1], "mail") == 0) {
2519 const char *res;
2520 unsigned int timeout_mail;
2521 if (!*args[2]) {
2522 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2523 file, linenum, args[0], args[1]);
2524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
2526 }
2527 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2528 if (res) {
2529 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2530 file, linenum, *res, args[0]);
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534 if (timeout_mail <= 0) {
2535 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
2538 }
2539 curmailers->timeout.mail = timeout_mail;
2540 } else {
2541 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2542 file, linenum, args[0], args[1]);
2543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
2545 }
2546 }
Simon Horman0d16a402015-01-30 11:22:58 +09002547 else if (*args[0] != 0) {
2548 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
2551 }
2552
2553out:
2554 free(errmsg);
2555 return err_code;
2556}
2557
Simon Horman9dc49962015-01-30 11:22:59 +09002558static void free_email_alert(struct proxy *p)
2559{
2560 free(p->email_alert.mailers.name);
2561 p->email_alert.mailers.name = NULL;
2562 free(p->email_alert.from);
2563 p->email_alert.from = NULL;
2564 free(p->email_alert.to);
2565 p->email_alert.to = NULL;
2566 free(p->email_alert.myhostname);
2567 p->email_alert.myhostname = NULL;
2568}
2569
Willy Tarreau3842f002009-06-14 11:39:52 +02002570int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571{
2572 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002573 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002574 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002575 int rc;
2576 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002577 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002578 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002579 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002580 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002581 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 if (!strcmp(args[0], "listen"))
2584 rc = PR_CAP_LISTEN;
2585 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002586 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002587 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002588 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002589 else
2590 rc = PR_CAP_NONE;
2591
2592 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 if (!*args[1]) {
2594 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002595 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_ABORT;
2598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002600
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002601 err = invalid_char(args[1]);
2602 if (err) {
2603 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2604 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002606 }
2607
Willy Tarreau8f50b682015-05-26 11:45:02 +02002608 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2609 if (curproxy) {
2610 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2611 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2612 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002614 }
2615
Vincent Bernat02779b62016-04-03 13:48:43 +02002616 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_ALERT | ERR_ABORT;
2619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002621
Willy Tarreau97cb7802010-01-03 20:23:58 +01002622 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 curproxy->next = proxy;
2624 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002625 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2626 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002627 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002629 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002630 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631
William Lallemand6e62fb62015-04-28 16:55:23 +02002632 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2633 if (curproxy->cap & PR_CAP_FE)
2634 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 }
2637
2638 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002639 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002640 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002641
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002644 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002645 curproxy->no_options = defproxy.no_options;
2646 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002647 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002648 curproxy->except_net = defproxy.except_net;
2649 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002650 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002651 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002653 if (defproxy.fwdfor_hdr_len) {
2654 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2655 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2656 }
2657
Willy Tarreaub86db342009-11-30 11:50:16 +01002658 if (defproxy.orgto_hdr_len) {
2659 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2660 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2661 }
2662
Mark Lamourinec2247f02012-01-04 13:02:01 -05002663 if (defproxy.server_id_hdr_len) {
2664 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2665 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2666 }
2667
Willy Tarreau977b8e42006-12-29 14:19:17 +01002668 if (curproxy->cap & PR_CAP_FE) {
2669 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002670 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002671 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672
2673 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002674 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2675 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676
2677 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679
Willy Tarreau977b8e42006-12-29 14:19:17 +01002680 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002681 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002682 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683 curproxy->fullconn = defproxy.fullconn;
2684 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002685 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002686 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002688 if (defproxy.check_req) {
2689 curproxy->check_req = calloc(1, defproxy.check_len);
2690 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2691 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002692 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002694 if (defproxy.expect_str) {
2695 curproxy->expect_str = strdup(defproxy.expect_str);
2696 if (defproxy.expect_regex) {
2697 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002698 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2699 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002700 }
2701 }
2702
Willy Tarreau67402132012-05-31 20:40:20 +02002703 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704 if (defproxy.cookie_name)
2705 curproxy->cookie_name = strdup(defproxy.cookie_name);
2706 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002707
2708 if (defproxy.dyncookie_key)
2709 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002710 if (defproxy.cookie_domain)
2711 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002712
Willy Tarreau31936852010-10-06 16:59:56 +02002713 if (defproxy.cookie_maxidle)
2714 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2715
2716 if (defproxy.cookie_maxlife)
2717 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2718
Emeric Brun647caf12009-06-30 17:57:00 +02002719 if (defproxy.rdp_cookie_name)
2720 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2721 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2722
Willy Tarreau01732802007-11-01 22:48:15 +01002723 if (defproxy.url_param_name)
2724 curproxy->url_param_name = strdup(defproxy.url_param_name);
2725 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002726
Benoitaffb4812009-03-25 13:02:10 +01002727 if (defproxy.hh_name)
2728 curproxy->hh_name = strdup(defproxy.hh_name);
2729 curproxy->hh_len = defproxy.hh_len;
2730 curproxy->hh_match_domain = defproxy.hh_match_domain;
2731
Willy Tarreauef9a3602012-12-08 22:29:20 +01002732 if (defproxy.conn_src.iface_name)
2733 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2734 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002735 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002736#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002737 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002738#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002739 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002742 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 if (defproxy.capture_name)
2744 curproxy->capture_name = strdup(defproxy.capture_name);
2745 curproxy->capture_namelen = defproxy.capture_namelen;
2746 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002750 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002751 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002752 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002753 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002754 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002755 curproxy->mon_net = defproxy.mon_net;
2756 curproxy->mon_mask = defproxy.mon_mask;
2757 if (defproxy.monitor_uri)
2758 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2759 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002760 if (defproxy.defbe.name)
2761 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002762
2763 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002764 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2765 if (curproxy->conf.logformat_string &&
2766 curproxy->conf.logformat_string != default_http_log_format &&
2767 curproxy->conf.logformat_string != default_tcp_log_format &&
2768 curproxy->conf.logformat_string != clf_http_log_format)
2769 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2770
2771 if (defproxy.conf.lfs_file) {
2772 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2773 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2774 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002775
2776 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2777 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2778 if (curproxy->conf.logformat_sd_string &&
2779 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2780 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2781
2782 if (defproxy.conf.lfsd_file) {
2783 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2784 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2785 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786 }
2787
2788 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002789 curproxy->timeout.connect = defproxy.timeout.connect;
2790 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002791 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002792 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002793 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002794 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002795 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002796 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002797 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002798 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002799 }
2800
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002802 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002803
2804 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002805 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002806 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002807 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002808 LIST_INIT(&node->list);
2809 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2810 }
2811
Willy Tarreau62a61232013-04-12 18:13:46 +02002812 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2813 if (curproxy->conf.uniqueid_format_string)
2814 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2815
Dragan Dosen43885c72015-10-01 13:18:13 +02002816 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002817
Willy Tarreau62a61232013-04-12 18:13:46 +02002818 if (defproxy.conf.uif_file) {
2819 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2820 curproxy->conf.uif_line = defproxy.conf.uif_line;
2821 }
William Lallemanda73203e2012-03-12 12:48:57 +01002822
2823 /* copy default header unique id */
2824 if (defproxy.header_unique_id)
2825 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2826
William Lallemand82fe75c2012-10-23 10:25:10 +02002827 /* default compression options */
2828 if (defproxy.comp != NULL) {
2829 curproxy->comp = calloc(1, sizeof(struct comp));
2830 curproxy->comp->algos = defproxy.comp->algos;
2831 curproxy->comp->types = defproxy.comp->types;
2832 }
2833
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002835 curproxy->conf.used_listener_id = EB_ROOT;
2836 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002837
Simon Horman98637e52014-06-20 12:30:16 +09002838 if (defproxy.check_path)
2839 curproxy->check_path = strdup(defproxy.check_path);
2840 if (defproxy.check_command)
2841 curproxy->check_command = strdup(defproxy.check_command);
2842
Simon Horman9dc49962015-01-30 11:22:59 +09002843 if (defproxy.email_alert.mailers.name)
2844 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2845 if (defproxy.email_alert.from)
2846 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2847 if (defproxy.email_alert.to)
2848 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2849 if (defproxy.email_alert.myhostname)
2850 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002851 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002852 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002853
Willy Tarreau93893792009-07-23 13:19:11 +02002854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 }
2856 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2857 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002858 /* FIXME-20070101: we should do this too at the end of the
2859 * config parsing to free all default values.
2860 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002861 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2862 err_code |= ERR_ABORT;
2863 goto out;
2864 }
2865
Willy Tarreaua534fea2008-08-03 12:19:50 +02002866 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002867 free(defproxy.check_command);
2868 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002869 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002870 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002871 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002872 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002873 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002874 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002875 free(defproxy.capture_name);
2876 free(defproxy.monitor_uri);
2877 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002878 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002879 free(defproxy.fwdfor_hdr_name);
2880 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002881 free(defproxy.orgto_hdr_name);
2882 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002883 free(defproxy.server_id_hdr_name);
2884 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002885 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002886 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002887 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002888 free(defproxy.expect_regex);
2889 defproxy.expect_regex = NULL;
2890 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002891
Willy Tarreau62a61232013-04-12 18:13:46 +02002892 if (defproxy.conf.logformat_string != default_http_log_format &&
2893 defproxy.conf.logformat_string != default_tcp_log_format &&
2894 defproxy.conf.logformat_string != clf_http_log_format)
2895 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002896
Willy Tarreau62a61232013-04-12 18:13:46 +02002897 free(defproxy.conf.uniqueid_format_string);
2898 free(defproxy.conf.lfs_file);
2899 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002900 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002901 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002902
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002903 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2904 free(defproxy.conf.logformat_sd_string);
2905 free(defproxy.conf.lfsd_file);
2906
Willy Tarreaua534fea2008-08-03 12:19:50 +02002907 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002908 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002909
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 /* we cannot free uri_auth because it might already be used */
2911 init_default_instance();
2912 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002913 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2914 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002915 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }
2918 else if (curproxy == NULL) {
2919 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002923
2924 /* update the current file and line being parsed */
2925 curproxy->conf.args.file = curproxy->conf.file;
2926 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002927
2928 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002929 if (!strcmp(args[0], "server") ||
2930 !strcmp(args[0], "default-server") ||
2931 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002932 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2933 if (err_code & ERR_FATAL)
2934 goto out;
2935 }
2936 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002937 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002938 int cur_arg;
2939
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 if (curproxy == &defproxy) {
2941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947
Willy Tarreau24709282013-03-10 21:32:12 +01002948 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002949 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002953 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002954
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002955 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002956
2957 /* use default settings for unix sockets */
2958 bind_conf->ux.uid = global.unix_bind.ux.uid;
2959 bind_conf->ux.gid = global.unix_bind.ux.gid;
2960 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002961
2962 /* NOTE: the following line might create several listeners if there
2963 * are comma-separated IPs or port ranges. So all further processing
2964 * will have to be applied to all listeners created after last_listen.
2965 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002966 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2967 if (errmsg && *errmsg) {
2968 indent_msg(&errmsg, 2);
2969 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002970 }
2971 else
2972 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2973 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
2976 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002977
Willy Tarreau4348fad2012-09-20 16:48:07 +02002978 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2979 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002980 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002981 }
2982
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002983 cur_arg = 2;
2984 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002985 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002986 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002987 char *err;
2988
Willy Tarreau26982662012-09-12 23:17:10 +02002989 kw = bind_find_kw(args[cur_arg]);
2990 if (kw) {
2991 char *err = NULL;
2992 int code;
2993
2994 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002995 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2996 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002997 cur_arg += 1 + kw->skip ;
2998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
3000 }
3001
Willy Tarreau4348fad2012-09-20 16:48:07 +02003002 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003003 err_code |= code;
3004
3005 if (code) {
3006 if (err && *err) {
3007 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003008 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003009 }
3010 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003011 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3012 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003013 if (code & ERR_FATAL) {
3014 free(err);
3015 cur_arg += 1 + kw->skip;
3016 goto out;
3017 }
3018 }
3019 free(err);
3020 cur_arg += 1 + kw->skip;
3021 continue;
3022 }
3023
Willy Tarreau8638f482012-09-18 18:01:17 +02003024 err = NULL;
3025 if (!bind_dumped) {
3026 bind_dump_kws(&err);
3027 indent_msg(&err, 4);
3028 bind_dumped = 1;
3029 }
3030
3031 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3032 file, linenum, args[0], args[1], args[cur_arg],
3033 err ? " Registered keywords :" : "", err ? err : "");
3034 free(err);
3035
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003038 }
Willy Tarreau93893792009-07-23 13:19:11 +02003039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
3041 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003042 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3044 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003048 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003050
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 /* flush useless bits */
3052 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003055 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003056 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003058
William Lallemanddf1425a2015-04-28 20:17:49 +02003059 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3060 goto out;
3061
Willy Tarreau1c47f852006-07-09 08:22:27 +02003062 if (!*args[1]) {
3063 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003067 }
3068
Willy Tarreaua534fea2008-08-03 12:19:50 +02003069 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003070 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003071 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003072 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003073 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3074
Willy Tarreau93893792009-07-23 13:19:11 +02003075 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003078 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3079 goto out;
3080
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3082 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3083 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3084 else {
3085 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 }
3089 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003090 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003091 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003092
3093 if (curproxy == &defproxy) {
3094 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003098 }
3099
William Lallemanddf1425a2015-04-28 20:17:49 +02003100 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3101 goto out;
3102
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003103 if (!*args[1]) {
3104 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003108 }
3109
3110 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003111 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003112 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003113
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003114 if (curproxy->uuid <= 0) {
3115 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003116 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003119 }
3120
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003121 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3122 if (node) {
3123 struct proxy *target = container_of(node, struct proxy, conf.id);
3124 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3125 file, linenum, proxy_type_str(curproxy), curproxy->id,
3126 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003131 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003132 else if (!strcmp(args[0], "description")) {
3133 int i, len=0;
3134 char *d;
3135
Cyril Bonté99ed3272010-01-24 23:29:44 +01003136 if (curproxy == &defproxy) {
3137 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3138 file, linenum, args[0]);
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
3141 }
3142
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003143 if (!*args[1]) {
3144 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3145 file, linenum, args[0]);
3146 return -1;
3147 }
3148
Willy Tarreau348acfe2014-04-14 15:00:39 +02003149 for (i = 1; *args[i]; i++)
3150 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003151
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003152 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003153 curproxy->desc = d;
3154
Willy Tarreau348acfe2014-04-14 15:00:39 +02003155 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3156 for (i = 2; *args[i]; i++)
3157 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003158
3159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003161 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 curproxy->state = PR_STSTOPPED;
3164 }
3165 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003166 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 curproxy->state = PR_STNEW;
3169 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003170 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3171 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003172 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003173
3174 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003175 unsigned int low, high;
3176
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003177 if (strcmp(args[cur_arg], "all") == 0) {
3178 set = 0;
3179 break;
3180 }
3181 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003182 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003183 }
3184 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003185 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003186 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003187 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003188 char *dash = strchr(args[cur_arg], '-');
3189
3190 low = high = str2uic(args[cur_arg]);
3191 if (dash)
3192 high = str2uic(dash + 1);
3193
3194 if (high < low) {
3195 unsigned int swap = low;
3196 low = high;
3197 high = swap;
3198 }
3199
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003200 if (low < 1 || high > LONGBITS) {
3201 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3202 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003205 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003206 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003207 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003208 }
3209 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003210 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3211 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003214 }
3215 cur_arg++;
3216 }
3217 curproxy->bind_proc = set;
3218 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003219 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003220 if (curproxy == &defproxy) {
3221 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003224 }
3225
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003226 err = invalid_char(args[1]);
3227 if (err) {
3228 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3229 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003231 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003232 }
3233
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003234 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003235 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3236 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003239 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003240 }
3241 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3242
3243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3244 err_code |= ERR_WARN;
3245
3246 if (*(args[1]) == 0) {
3247 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3248 file, linenum, args[0]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252 free(curproxy->dyncookie_key);
3253 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3256 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257
Willy Tarreau977b8e42006-12-29 14:19:17 +01003258 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003260
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 if (*(args[1]) == 0) {
3262 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003267
Willy Tarreau67402132012-05-31 20:40:20 +02003268 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003269 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003270 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003271 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 curproxy->cookie_name = strdup(args[1]);
3273 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003274
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 cur_arg = 2;
3276 while (*(args[cur_arg])) {
3277 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003278 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 }
3280 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003281 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
3283 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003284 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 }
3286 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003287 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
3289 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003290 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003292 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003293 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003296 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003298 else if (!strcmp(args[cur_arg], "httponly")) {
3299 curproxy->ck_opts |= PR_CK_HTTPONLY;
3300 }
3301 else if (!strcmp(args[cur_arg], "secure")) {
3302 curproxy->ck_opts |= PR_CK_SECURE;
3303 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003304 else if (!strcmp(args[cur_arg], "domain")) {
3305 if (!*args[cur_arg + 1]) {
3306 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3307 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003310 }
3311
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003312 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003313 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003314 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3315 " dots nor does not start with a dot."
3316 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003317 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003318 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003319 }
3320
3321 err = invalid_domainchar(args[cur_arg + 1]);
3322 if (err) {
3323 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3324 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003327 }
3328
Willy Tarreau68a897b2009-12-03 23:28:34 +01003329 if (!curproxy->cookie_domain) {
3330 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3331 } else {
3332 /* one domain was already specified, add another one by
3333 * building the string which will be returned along with
3334 * the cookie.
3335 */
3336 char *new_ptr;
3337 int new_len = strlen(curproxy->cookie_domain) +
3338 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3339 new_ptr = malloc(new_len);
3340 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3341 free(curproxy->cookie_domain);
3342 curproxy->cookie_domain = new_ptr;
3343 }
Willy Tarreau31936852010-10-06 16:59:56 +02003344 cur_arg++;
3345 }
3346 else if (!strcmp(args[cur_arg], "maxidle")) {
3347 unsigned int maxidle;
3348 const char *res;
3349
3350 if (!*args[cur_arg + 1]) {
3351 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3352 file, linenum, args[cur_arg]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
3357 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3358 if (res) {
3359 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3360 file, linenum, *res, args[cur_arg]);
3361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
3363 }
3364 curproxy->cookie_maxidle = maxidle;
3365 cur_arg++;
3366 }
3367 else if (!strcmp(args[cur_arg], "maxlife")) {
3368 unsigned int maxlife;
3369 const char *res;
3370
3371 if (!*args[cur_arg + 1]) {
3372 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3373 file, linenum, args[cur_arg]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377
3378 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3379 if (res) {
3380 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3381 file, linenum, *res, args[cur_arg]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003386 cur_arg++;
3387 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003388 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003389
3390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3391 err_code |= ERR_WARN;
3392 curproxy->ck_opts |= PR_CK_DYNAMIC;
3393 }
3394
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003396 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 +02003397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
3401 cur_arg++;
3402 }
Willy Tarreau67402132012-05-31 20:40:20 +02003403 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3405 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 }
3408
Willy Tarreau67402132012-05-31 20:40:20 +02003409 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3411 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003414
Willy Tarreau67402132012-05-31 20:40:20 +02003415 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003416 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3417 file, linenum);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003421 else if (!strcmp(args[0], "email-alert")) {
3422 if (*(args[1]) == 0) {
3423 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3424 file, linenum, args[0]);
3425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
3427 }
3428
3429 if (!strcmp(args[1], "from")) {
3430 if (*(args[1]) == 0) {
3431 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3432 file, linenum, args[1]);
3433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
3435 }
3436 free(curproxy->email_alert.from);
3437 curproxy->email_alert.from = strdup(args[2]);
3438 }
3439 else if (!strcmp(args[1], "mailers")) {
3440 if (*(args[1]) == 0) {
3441 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3442 file, linenum, args[1]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446 free(curproxy->email_alert.mailers.name);
3447 curproxy->email_alert.mailers.name = strdup(args[2]);
3448 }
3449 else if (!strcmp(args[1], "myhostname")) {
3450 if (*(args[1]) == 0) {
3451 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3452 file, linenum, args[1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 free(curproxy->email_alert.myhostname);
3457 curproxy->email_alert.myhostname = strdup(args[2]);
3458 }
Simon Horman64e34162015-02-06 11:11:57 +09003459 else if (!strcmp(args[1], "level")) {
3460 curproxy->email_alert.level = get_log_level(args[2]);
3461 if (curproxy->email_alert.level < 0) {
3462 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3463 file, linenum, args[1], args[2]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467 }
Simon Horman9dc49962015-01-30 11:22:59 +09003468 else if (!strcmp(args[1], "to")) {
3469 if (*(args[1]) == 0) {
3470 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3471 file, linenum, args[1]);
3472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
3475 free(curproxy->email_alert.to);
3476 curproxy->email_alert.to = strdup(args[2]);
3477 }
3478 else {
3479 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3480 file, linenum, args[1]);
3481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
3483 }
Simon Horman64e34162015-02-06 11:11:57 +09003484 /* Indicate that the email_alert is at least partially configured */
3485 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003486 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003487 else if (!strcmp(args[0], "external-check")) {
3488 if (*(args[1]) == 0) {
3489 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3490 file, linenum, args[0]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
3494
3495 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003496 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003497 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003498 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003499 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3500 file, linenum, args[1]);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
3503 }
3504 free(curproxy->check_command);
3505 curproxy->check_command = strdup(args[2]);
3506 }
3507 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003508 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003509 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003510 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003511 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3512 file, linenum, args[1]);
3513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
3515 }
3516 free(curproxy->check_path);
3517 curproxy->check_path = strdup(args[2]);
3518 }
3519 else {
3520 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3521 file, linenum, args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
3525 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003526 else if (!strcmp(args[0], "persist")) { /* persist */
3527 if (*(args[1]) == 0) {
3528 Alert("parsing [%s:%d] : missing persist method.\n",
3529 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003532 }
3533
3534 if (!strncmp(args[1], "rdp-cookie", 10)) {
3535 curproxy->options2 |= PR_O2_RDPC_PRST;
3536
Emeric Brunb982a3d2010-01-04 15:45:53 +01003537 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003538 const char *beg, *end;
3539
3540 beg = args[1] + 11;
3541 end = strchr(beg, ')');
3542
William Lallemanddf1425a2015-04-28 20:17:49 +02003543 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3544 goto out;
3545
Emeric Brun647caf12009-06-30 17:57:00 +02003546 if (!end || end == beg) {
3547 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3548 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003551 }
3552
3553 free(curproxy->rdp_cookie_name);
3554 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3555 curproxy->rdp_cookie_len = end-beg;
3556 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003557 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003558 free(curproxy->rdp_cookie_name);
3559 curproxy->rdp_cookie_name = strdup("msts");
3560 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3561 }
3562 else { /* syntax */
3563 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3564 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003567 }
3568 }
3569 else {
3570 Alert("parsing [%s:%d] : unknown persist method.\n",
3571 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003574 }
3575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003577 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
3580 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003581 else if (!strcmp(args[0], "load-server-state-from-file")) {
3582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3583 err_code |= ERR_WARN;
3584 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3585 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3586 }
3587 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3588 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3589 }
3590 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3591 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3592 }
3593 else {
3594 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3595 file, linenum, args[0], args[1]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599 }
3600 else if (!strcmp(args[0], "server-state-file-name")) {
3601 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3602 err_code |= ERR_WARN;
3603 if (*(args[1]) == 0) {
3604 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3605 file, linenum, args[0]);
3606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
3608 }
3609 else if (!strcmp(args[1], "use-backend-name"))
3610 curproxy->server_state_file_name = strdup(curproxy->id);
3611 else
3612 curproxy->server_state_file_name = strdup(args[1]);
3613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003615 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003617
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003619 if (curproxy == &defproxy) {
3620 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624
William Lallemand1a748ae2015-05-19 16:37:23 +02003625 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3626 goto out;
3627
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 if (*(args[4]) == 0) {
3629 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003634 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 curproxy->capture_name = strdup(args[2]);
3636 curproxy->capture_namelen = strlen(curproxy->capture_name);
3637 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 curproxy->to_log |= LW_COOKIE;
3639 }
3640 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3641 struct cap_hdr *hdr;
3642
3643 if (curproxy == &defproxy) {
3644 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 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 }
3648
William Lallemand1a748ae2015-05-19 16:37:23 +02003649 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3650 goto out;
3651
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3653 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3654 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 }
3658
Vincent Bernat02779b62016-04-03 13:48:43 +02003659 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 hdr->next = curproxy->req_cap;
3661 hdr->name = strdup(args[3]);
3662 hdr->namelen = strlen(args[3]);
3663 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003664 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 hdr->index = curproxy->nb_req_cap++;
3666 curproxy->req_cap = hdr;
3667 curproxy->to_log |= LW_REQHDR;
3668 }
3669 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3670 struct cap_hdr *hdr;
3671
3672 if (curproxy == &defproxy) {
3673 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 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 }
3677
William Lallemand1a748ae2015-05-19 16:37:23 +02003678 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3679 goto out;
3680
Willy Tarreaubaaee002006-06-26 02:48:02 +02003681 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3682 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3683 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003687 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 hdr->next = curproxy->rsp_cap;
3689 hdr->name = strdup(args[3]);
3690 hdr->namelen = strlen(args[3]);
3691 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003692 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 hdr->index = curproxy->nb_rsp_cap++;
3694 curproxy->rsp_cap = hdr;
3695 curproxy->to_log |= LW_RSPHDR;
3696 }
3697 else {
3698 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 }
3703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003705 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003707
William Lallemanddf1425a2015-04-28 20:17:49 +02003708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3709 goto out;
3710
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 if (*(args[1]) == 0) {
3712 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3713 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
3717 curproxy->conn_retries = atol(args[1]);
3718 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003719 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003720 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003721
3722 if (curproxy == &defproxy) {
3723 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727
Willy Tarreau20b0de52012-12-24 15:45:22 +01003728 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003729 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003730 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3731 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3732 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3733 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003734 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 +01003735 file, linenum, args[0]);
3736 err_code |= ERR_WARN;
3737 }
3738
Willy Tarreauff011f22011-01-06 17:51:27 +01003739 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003740
Willy Tarreauff011f22011-01-06 17:51:27 +01003741 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003742 err_code |= ERR_ALERT | ERR_ABORT;
3743 goto out;
3744 }
3745
Willy Tarreau5002f572014-04-23 01:32:02 +02003746 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003747 err_code |= warnif_cond_conflicts(rule->cond,
3748 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3749 file, linenum);
3750
Willy Tarreauff011f22011-01-06 17:51:27 +01003751 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003752 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003753 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003754 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003755
3756 if (curproxy == &defproxy) {
3757 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
3760 }
3761
3762 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003763 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003764 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3765 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003766 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3767 file, linenum, args[0]);
3768 err_code |= ERR_WARN;
3769 }
3770
3771 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3772
3773 if (!rule) {
3774 err_code |= ERR_ALERT | ERR_ABORT;
3775 goto out;
3776 }
3777
3778 err_code |= warnif_cond_conflicts(rule->cond,
3779 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3780 file, linenum);
3781
3782 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3783 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003784 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3785 /* set the header name and length into the proxy structure */
3786 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3787 err_code |= ERR_WARN;
3788
3789 if (!*args[1]) {
3790 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3791 file, linenum, args[0]);
3792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
3794 }
3795
3796 /* set the desired header name */
3797 free(curproxy->server_id_hdr_name);
3798 curproxy->server_id_hdr_name = strdup(args[1]);
3799 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3800 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003801 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003802 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003803
Willy Tarreaub099aca2008-10-12 17:26:37 +02003804 if (curproxy == &defproxy) {
3805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003808 }
3809
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003810 /* emulate "block" using "http-request block". Since these rules are supposed to
3811 * be processed before all http-request rules, we put them into their own list
3812 * and will insert them at the end.
3813 */
3814 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3815 if (!rule) {
3816 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003817 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003818 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003819 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3820 err_code |= warnif_cond_conflicts(rule->cond,
3821 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3822 file, linenum);
3823 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003824
3825 if (!already_warned(WARN_BLOCK_DEPRECATED))
3826 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]);
3827
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003828 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003829 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003830 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003831
Cyril Bonté99ed3272010-01-24 23:29:44 +01003832 if (curproxy == &defproxy) {
3833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837
Willy Tarreaube4653b2015-05-28 15:26:58 +02003838 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003839 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3840 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003843 }
3844
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003845 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003846 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003847 err_code |= warnif_cond_conflicts(rule->cond,
3848 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3849 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003850 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003851 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003852 struct switching_rule *rule;
3853
Willy Tarreaub099aca2008-10-12 17:26:37 +02003854 if (curproxy == &defproxy) {
3855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003858 }
3859
Willy Tarreau55ea7572007-06-17 19:56:27 +02003860 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003862
3863 if (*(args[1]) == 0) {
3864 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003867 }
3868
Willy Tarreauf51658d2014-04-23 01:21:56 +02003869 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003870 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003871 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3872 file, linenum, errmsg);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003876
Willy Tarreauf51658d2014-04-23 01:21:56 +02003877 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003878 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003879 else if (*args[2]) {
3880 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3881 file, linenum, args[2]);
3882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003885
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003886 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003887 if (!rule) {
3888 Alert("Out of memory error.\n");
3889 goto out;
3890 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003891 rule->cond = cond;
3892 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003893 rule->line = linenum;
3894 rule->file = strdup(file);
3895 if (!rule->file) {
3896 Alert("Out of memory error.\n");
3897 goto out;
3898 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003899 LIST_INIT(&rule->list);
3900 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3901 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003902 else if (strcmp(args[0], "use-server") == 0) {
3903 struct server_rule *rule;
3904
3905 if (curproxy == &defproxy) {
3906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
3910
3911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3912 err_code |= ERR_WARN;
3913
3914 if (*(args[1]) == 0) {
3915 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918 }
3919
3920 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3921 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3922 file, linenum, args[0]);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925 }
3926
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003927 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003928 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3929 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
3932 }
3933
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003934 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003935
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003936 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003937 rule->cond = cond;
3938 rule->srv.name = strdup(args[1]);
3939 LIST_INIT(&rule->list);
3940 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3941 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3942 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003943 else if ((!strcmp(args[0], "force-persist")) ||
3944 (!strcmp(args[0], "ignore-persist"))) {
3945 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003946
3947 if (curproxy == &defproxy) {
3948 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
3951 }
3952
3953 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3954 err_code |= ERR_WARN;
3955
Willy Tarreauef6494c2010-01-28 17:12:36 +01003956 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003957 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3958 file, linenum, args[0]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003963 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003964 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3965 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003970 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3971 * where force-persist is applied.
3972 */
3973 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003974
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003975 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003976 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003977 if (!strcmp(args[0], "force-persist")) {
3978 rule->type = PERSIST_TYPE_FORCE;
3979 } else {
3980 rule->type = PERSIST_TYPE_IGNORE;
3981 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003982 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003983 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003984 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003985 else if (!strcmp(args[0], "stick-table")) {
3986 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003987 struct proxy *other;
3988
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003989 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003990 if (other) {
3991 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3992 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003996
Emeric Brun32da3c42010-09-23 18:39:19 +02003997 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003998 curproxy->table.type = (unsigned int)-1;
3999 while (*args[myidx]) {
4000 const char *err;
4001
4002 if (strcmp(args[myidx], "size") == 0) {
4003 myidx++;
4004 if (!*(args[myidx])) {
4005 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4006 file, linenum, args[myidx-1]);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
4010 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4011 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4012 file, linenum, *err, args[myidx-1]);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004016 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004017 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004018 else if (strcmp(args[myidx], "peers") == 0) {
4019 myidx++;
Godbach50523162013-12-11 19:48:57 +08004020 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004021 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4022 file, linenum, args[myidx-1]);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
Godbach50523162013-12-11 19:48:57 +08004025 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004026 curproxy->table.peers.name = strdup(args[myidx++]);
4027 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004028 else if (strcmp(args[myidx], "expire") == 0) {
4029 myidx++;
4030 if (!*(args[myidx])) {
4031 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4032 file, linenum, args[myidx-1]);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4037 if (err) {
4038 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4039 file, linenum, *err, args[myidx-1]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004043 if (val > INT_MAX) {
4044 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4045 file, linenum, val);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004049 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004050 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004051 }
4052 else if (strcmp(args[myidx], "nopurge") == 0) {
4053 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004054 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004055 }
4056 else if (strcmp(args[myidx], "type") == 0) {
4057 myidx++;
4058 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4059 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4060 file, linenum, args[myidx]);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004064 /* myidx already points to next arg */
4065 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004066 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004067 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004068 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004069
4070 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004071 nw = args[myidx];
4072 while (*nw) {
4073 /* the "store" keyword supports a comma-separated list */
4074 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004075 sa = NULL; /* store arg */
4076 while (*nw && *nw != ',') {
4077 if (*nw == '(') {
4078 *nw = 0;
4079 sa = ++nw;
4080 while (*nw != ')') {
4081 if (!*nw) {
4082 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4083 file, linenum, args[0], cw);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087 nw++;
4088 }
4089 *nw = '\0';
4090 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004091 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004092 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004093 if (*nw)
4094 *nw++ = '\0';
4095 type = stktable_get_data_type(cw);
4096 if (type < 0) {
4097 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4098 file, linenum, args[0], cw);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
Willy Tarreauac782882010-06-20 10:41:54 +02004102
4103 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4104 switch (err) {
4105 case PE_NONE: break;
4106 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004107 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4108 file, linenum, args[0], cw);
4109 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004110 break;
4111
4112 case PE_ARG_MISSING:
4113 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4114 file, linenum, args[0], cw);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117
4118 case PE_ARG_NOT_USED:
4119 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4120 file, linenum, args[0], cw);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
4123
4124 default:
4125 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4126 file, linenum, args[0], cw);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004129 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004130 }
4131 myidx++;
4132 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004133 else {
4134 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4135 file, linenum, args[myidx]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004138 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004139 }
4140
4141 if (!curproxy->table.size) {
4142 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4143 file, linenum);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147
4148 if (curproxy->table.type == (unsigned int)-1) {
4149 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4150 file, linenum);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154 }
4155 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004157 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 int myidx = 0;
4159 const char *name = NULL;
4160 int flags;
4161
4162 if (curproxy == &defproxy) {
4163 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
4167
4168 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4169 err_code |= ERR_WARN;
4170 goto out;
4171 }
4172
4173 myidx++;
4174 if ((strcmp(args[myidx], "store") == 0) ||
4175 (strcmp(args[myidx], "store-request") == 0)) {
4176 myidx++;
4177 flags = STK_IS_STORE;
4178 }
4179 else if (strcmp(args[myidx], "store-response") == 0) {
4180 myidx++;
4181 flags = STK_IS_STORE | STK_ON_RSP;
4182 }
4183 else if (strcmp(args[myidx], "match") == 0) {
4184 myidx++;
4185 flags = STK_IS_MATCH;
4186 }
4187 else if (strcmp(args[myidx], "on") == 0) {
4188 myidx++;
4189 flags = STK_IS_MATCH | STK_IS_STORE;
4190 }
4191 else {
4192 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196
4197 if (*(args[myidx]) == 0) {
4198 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
4202
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004203 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004204 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004205 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004206 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
4209 }
4210
4211 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004212 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4213 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4214 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004215 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004216 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004217 goto out;
4218 }
4219 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004220 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4221 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4222 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004223 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004224 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004225 goto out;
4226 }
4227 }
4228
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004229 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004230 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004231
Emeric Brunb982a3d2010-01-04 15:45:53 +01004232 if (strcmp(args[myidx], "table") == 0) {
4233 myidx++;
4234 name = args[myidx++];
4235 }
4236
Willy Tarreauef6494c2010-01-28 17:12:36 +01004237 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004238 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004239 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4240 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004241 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004242 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004243 goto out;
4244 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004245 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004246 else if (*(args[myidx])) {
4247 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4248 file, linenum, args[0], args[myidx]);
4249 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004250 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004251 goto out;
4252 }
Emeric Brun97679e72010-09-23 17:56:44 +02004253 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004254 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004255 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004256 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004257
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004258 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004259 rule->cond = cond;
4260 rule->expr = expr;
4261 rule->flags = flags;
4262 rule->table.name = name ? strdup(name) : NULL;
4263 LIST_INIT(&rule->list);
4264 if (flags & STK_ON_RSP)
4265 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4266 else
4267 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 else if (!strcmp(args[0], "stats")) {
4270 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4271 curproxy->uri_auth = NULL; /* we must detach from the default config */
4272
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004273 if (!*args[1]) {
4274 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004275 } else if (!strcmp(args[1], "admin")) {
4276 struct stats_admin_rule *rule;
4277
4278 if (curproxy == &defproxy) {
4279 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283
4284 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4285 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4286 err_code |= ERR_ALERT | ERR_ABORT;
4287 goto out;
4288 }
4289
4290 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4291 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4292 file, linenum, args[0], args[1]);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004296 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004297 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4298 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004303 err_code |= warnif_cond_conflicts(cond,
4304 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4305 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004306
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004307 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004308 rule->cond = cond;
4309 LIST_INIT(&rule->list);
4310 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 } else if (!strcmp(args[1], "uri")) {
4312 if (*(args[2]) == 0) {
4313 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4317 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_ABORT;
4319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 }
4321 } else if (!strcmp(args[1], "realm")) {
4322 if (*(args[2]) == 0) {
4323 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004326 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_ABORT;
4329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004331 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004332 unsigned interval;
4333
4334 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4335 if (err) {
4336 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4337 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004340 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4341 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004342 err_code |= ERR_ALERT | ERR_ABORT;
4343 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004344 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004345 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004346 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004347
4348 if (curproxy == &defproxy) {
4349 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353
4354 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4355 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4356 err_code |= ERR_ALERT | ERR_ABORT;
4357 goto out;
4358 }
4359
Willy Tarreauff011f22011-01-06 17:51:27 +01004360 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004361 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004362 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4363 file, linenum, args[0]);
4364 err_code |= ERR_WARN;
4365 }
4366
Willy Tarreauff011f22011-01-06 17:51:27 +01004367 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004368
Willy Tarreauff011f22011-01-06 17:51:27 +01004369 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004370 err_code |= ERR_ALERT | ERR_ABORT;
4371 goto out;
4372 }
4373
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004374 err_code |= warnif_cond_conflicts(rule->cond,
4375 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4376 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004377 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004378
Willy Tarreaubaaee002006-06-26 02:48:02 +02004379 } else if (!strcmp(args[1], "auth")) {
4380 if (*(args[2]) == 0) {
4381 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4385 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 }
4389 } else if (!strcmp(args[1], "scope")) {
4390 if (*(args[2]) == 0) {
4391 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4395 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_ABORT;
4397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 }
4399 } else if (!strcmp(args[1], "enable")) {
4400 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4401 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_ABORT;
4403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004405 } else if (!strcmp(args[1], "hide-version")) {
4406 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4407 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_ABORT;
4409 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004410 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004411 } else if (!strcmp(args[1], "show-legends")) {
4412 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4413 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4414 err_code |= ERR_ALERT | ERR_ABORT;
4415 goto out;
4416 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004417 } else if (!strcmp(args[1], "show-node")) {
4418
4419 if (*args[2]) {
4420 int i;
4421 char c;
4422
4423 for (i=0; args[2][i]; i++) {
4424 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004425 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4426 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004427 break;
4428 }
4429
4430 if (!i || args[2][i]) {
4431 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4432 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4433 file, linenum, args[0], args[1]);
4434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
4436 }
4437 }
4438
4439 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4440 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4441 err_code |= ERR_ALERT | ERR_ABORT;
4442 goto out;
4443 }
4444 } else if (!strcmp(args[1], "show-desc")) {
4445 char *desc = NULL;
4446
4447 if (*args[2]) {
4448 int i, len=0;
4449 char *d;
4450
Willy Tarreau348acfe2014-04-14 15:00:39 +02004451 for (i = 2; *args[i]; i++)
4452 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004453
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004454 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004455
Willy Tarreau348acfe2014-04-14 15:00:39 +02004456 d += snprintf(d, desc + len - d, "%s", args[2]);
4457 for (i = 3; *args[i]; i++)
4458 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004459 }
4460
4461 if (!*args[2] && !global.desc)
4462 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4463 file, linenum, args[1]);
4464 else {
4465 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4466 free(desc);
4467 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4468 err_code |= ERR_ALERT | ERR_ABORT;
4469 goto out;
4470 }
4471 free(desc);
4472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004474stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004475 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 +01004476 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 }
4480 }
4481 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004482 int optnum;
4483
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004484 if (*(args[1]) == '\0') {
4485 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4486 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004490
4491 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4492 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004493 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4494 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4495 file, linenum, cfg_opts[optnum].name);
4496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
4498 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004499 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4500 goto out;
4501
Willy Tarreau93893792009-07-23 13:19:11 +02004502 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4503 err_code |= ERR_WARN;
4504 goto out;
4505 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004506
Willy Tarreau3842f002009-06-14 11:39:52 +02004507 curproxy->no_options &= ~cfg_opts[optnum].val;
4508 curproxy->options &= ~cfg_opts[optnum].val;
4509
4510 switch (kwm) {
4511 case KWM_STD:
4512 curproxy->options |= cfg_opts[optnum].val;
4513 break;
4514 case KWM_NO:
4515 curproxy->no_options |= cfg_opts[optnum].val;
4516 break;
4517 case KWM_DEF: /* already cleared */
4518 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004519 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004520
Willy Tarreau93893792009-07-23 13:19:11 +02004521 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004522 }
4523 }
4524
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004525 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4526 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004527 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4528 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4529 file, linenum, cfg_opts2[optnum].name);
4530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
4532 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004533 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4534 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004535 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4536 err_code |= ERR_WARN;
4537 goto out;
4538 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004539
Willy Tarreau3842f002009-06-14 11:39:52 +02004540 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4541 curproxy->options2 &= ~cfg_opts2[optnum].val;
4542
4543 switch (kwm) {
4544 case KWM_STD:
4545 curproxy->options2 |= cfg_opts2[optnum].val;
4546 break;
4547 case KWM_NO:
4548 curproxy->no_options2 |= cfg_opts2[optnum].val;
4549 break;
4550 case KWM_DEF: /* already cleared */
4551 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004552 }
Willy Tarreau93893792009-07-23 13:19:11 +02004553 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004554 }
4555 }
4556
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004557 /* HTTP options override each other. They can be cancelled using
4558 * "no option xxx" which only switches to default mode if the mode
4559 * was this one (useful for cancelling options set in defaults
4560 * sections).
4561 */
4562 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004563 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4564 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004565 if (kwm == KWM_STD) {
4566 curproxy->options &= ~PR_O_HTTP_MODE;
4567 curproxy->options |= PR_O_HTTP_PCL;
4568 goto out;
4569 }
4570 else if (kwm == KWM_NO) {
4571 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4572 curproxy->options &= ~PR_O_HTTP_MODE;
4573 goto out;
4574 }
4575 }
4576 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004577 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4578 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004579 if (kwm == KWM_STD) {
4580 curproxy->options &= ~PR_O_HTTP_MODE;
4581 curproxy->options |= PR_O_HTTP_FCL;
4582 goto out;
4583 }
4584 else if (kwm == KWM_NO) {
4585 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4586 curproxy->options &= ~PR_O_HTTP_MODE;
4587 goto out;
4588 }
4589 }
4590 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004591 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4592 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004593 if (kwm == KWM_STD) {
4594 curproxy->options &= ~PR_O_HTTP_MODE;
4595 curproxy->options |= PR_O_HTTP_SCL;
4596 goto out;
4597 }
4598 else if (kwm == KWM_NO) {
4599 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4600 curproxy->options &= ~PR_O_HTTP_MODE;
4601 goto out;
4602 }
4603 }
4604 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004605 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4606 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004607 if (kwm == KWM_STD) {
4608 curproxy->options &= ~PR_O_HTTP_MODE;
4609 curproxy->options |= PR_O_HTTP_KAL;
4610 goto out;
4611 }
4612 else if (kwm == KWM_NO) {
4613 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4614 curproxy->options &= ~PR_O_HTTP_MODE;
4615 goto out;
4616 }
4617 }
4618 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004619 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4620 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004621 if (kwm == KWM_STD) {
4622 curproxy->options &= ~PR_O_HTTP_MODE;
4623 curproxy->options |= PR_O_HTTP_TUN;
4624 goto out;
4625 }
4626 else if (kwm == KWM_NO) {
4627 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4628 curproxy->options &= ~PR_O_HTTP_MODE;
4629 goto out;
4630 }
4631 }
4632
Joseph Lynch726ab712015-05-11 23:25:34 -07004633 /* Redispatch can take an integer argument that control when the
4634 * resispatch occurs. All values are relative to the retries option.
4635 * This can be cancelled using "no option xxx".
4636 */
4637 if (strcmp(args[1], "redispatch") == 0) {
4638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4639 err_code |= ERR_WARN;
4640 goto out;
4641 }
4642
4643 curproxy->no_options &= ~PR_O_REDISP;
4644 curproxy->options &= ~PR_O_REDISP;
4645
4646 switch (kwm) {
4647 case KWM_STD:
4648 curproxy->options |= PR_O_REDISP;
4649 curproxy->redispatch_after = -1;
4650 if(*args[2]) {
4651 curproxy->redispatch_after = atol(args[2]);
4652 }
4653 break;
4654 case KWM_NO:
4655 curproxy->no_options |= PR_O_REDISP;
4656 curproxy->redispatch_after = 0;
4657 break;
4658 case KWM_DEF: /* already cleared */
4659 break;
4660 }
4661 goto out;
4662 }
4663
Willy Tarreau3842f002009-06-14 11:39:52 +02004664 if (kwm != KWM_STD) {
4665 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004666 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004669 }
4670
Emeric Brun3a058f32009-06-30 18:26:00 +02004671 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004672 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004674 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004675 if (*(args[2]) != '\0') {
4676 if (!strcmp(args[2], "clf")) {
4677 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004678 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004679 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004680 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004683 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004684 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4685 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004686 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004687 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4688 char *oldlogformat = "log-format";
4689 char *clflogformat = "";
4690
4691 if (curproxy->conf.logformat_string == default_http_log_format)
4692 oldlogformat = "option httplog";
4693 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4694 oldlogformat = "option tcplog";
4695 else if (curproxy->conf.logformat_string == clf_http_log_format)
4696 oldlogformat = "option httplog clf";
4697 if (logformat == clf_http_log_format)
4698 clflogformat = " clf";
4699 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4700 file, linenum, clflogformat, oldlogformat);
4701 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004702 if (curproxy->conf.logformat_string != default_http_log_format &&
4703 curproxy->conf.logformat_string != default_tcp_log_format &&
4704 curproxy->conf.logformat_string != clf_http_log_format)
4705 free(curproxy->conf.logformat_string);
4706 curproxy->conf.logformat_string = logformat;
4707
4708 free(curproxy->conf.lfs_file);
4709 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4710 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004711 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004712 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004713 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4714 char *oldlogformat = "log-format";
4715
4716 if (curproxy->conf.logformat_string == default_http_log_format)
4717 oldlogformat = "option httplog";
4718 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4719 oldlogformat = "option tcplog";
4720 else if (curproxy->conf.logformat_string == clf_http_log_format)
4721 oldlogformat = "option httplog clf";
4722 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4723 file, linenum, oldlogformat);
4724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004725 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004726 if (curproxy->conf.logformat_string != default_http_log_format &&
4727 curproxy->conf.logformat_string != default_tcp_log_format &&
4728 curproxy->conf.logformat_string != clf_http_log_format)
4729 free(curproxy->conf.logformat_string);
4730 curproxy->conf.logformat_string = default_tcp_log_format;
4731
4732 free(curproxy->conf.lfs_file);
4733 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4734 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004735
4736 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4737 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004740 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004741 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004743
William Lallemanddf1425a2015-04-28 20:17:49 +02004744 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4745 goto out;
4746
Willy Tarreau13943ab2006-12-31 00:24:10 +01004747 if (curproxy->cap & PR_CAP_FE)
4748 curproxy->options |= PR_O_TCP_CLI_KA;
4749 if (curproxy->cap & PR_CAP_BE)
4750 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
4752 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004753 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004754 err_code |= ERR_WARN;
4755
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004757 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004758 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004759 curproxy->options2 &= ~PR_O2_CHK_ANY;
4760 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 if (!*args[2]) { /* no argument */
4762 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4763 curproxy->check_len = strlen(DEF_CHECK_REQ);
4764 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004765 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004766 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004768 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004770 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 if (*args[4])
4772 reqlen += strlen(args[4]);
4773 else
4774 reqlen += strlen("HTTP/1.0");
4775
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004776 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004778 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004780 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4781 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004782 }
4783 else if (!strcmp(args[1], "ssl-hello-chk")) {
4784 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004786 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004787
Willy Tarreaua534fea2008-08-03 12:19:50 +02004788 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004789 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004790 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004791 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004792
4793 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 }
Willy Tarreau23677902007-05-08 23:50:35 +02004796 else if (!strcmp(args[1], "smtpchk")) {
4797 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004798 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004799 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004800 curproxy->options2 &= ~PR_O2_CHK_ANY;
4801 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004802
4803 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4804 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4805 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4806 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4807 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4808 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004809 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004810 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4811 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4812 } else {
4813 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4814 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4815 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4816 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4817 }
4818 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004819 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4820 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004821 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004822 else if (!strcmp(args[1], "pgsql-check")) {
4823 /* use PostgreSQL request to check servers' health */
4824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4825 err_code |= ERR_WARN;
4826
4827 free(curproxy->check_req);
4828 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004829 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004830 curproxy->options2 |= PR_O2_PGSQL_CHK;
4831
4832 if (*(args[2])) {
4833 int cur_arg = 2;
4834
4835 while (*(args[cur_arg])) {
4836 if (strcmp(args[cur_arg], "user") == 0) {
4837 char * packet;
4838 uint32_t packet_len;
4839 uint32_t pv;
4840
4841 /* suboption header - needs additional argument for it */
4842 if (*(args[cur_arg+1]) == 0) {
4843 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4844 file, linenum, args[0], args[1], args[cur_arg]);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
4848
4849 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4850 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4851 pv = htonl(0x30000); /* protocol version 3.0 */
4852
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004853 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004854
4855 memcpy(packet + 4, &pv, 4);
4856
4857 /* copy "user" */
4858 memcpy(packet + 8, "user", 4);
4859
4860 /* copy username */
4861 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4862
4863 free(curproxy->check_req);
4864 curproxy->check_req = packet;
4865 curproxy->check_len = packet_len;
4866
4867 packet_len = htonl(packet_len);
4868 memcpy(packet, &packet_len, 4);
4869 cur_arg += 2;
4870 } else {
4871 /* unknown suboption - catchall */
4872 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4873 file, linenum, args[0], args[1]);
4874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
4876 }
4877 } /* end while loop */
4878 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004879 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4880 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004881 }
4882
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004883 else if (!strcmp(args[1], "redis-check")) {
4884 /* use REDIS PING request to check servers' health */
4885 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4886 err_code |= ERR_WARN;
4887
4888 free(curproxy->check_req);
4889 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004890 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004891 curproxy->options2 |= PR_O2_REDIS_CHK;
4892
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004893 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004894 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4895 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004896
4897 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4898 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004899 }
4900
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004901 else if (!strcmp(args[1], "mysql-check")) {
4902 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004903 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4904 err_code |= ERR_WARN;
4905
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004906 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004907 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004908 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004909 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004910
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004911 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004912 * const char mysql40_client_auth_pkt[] = {
4913 * "\x0e\x00\x00" // packet length
4914 * "\x01" // packet number
4915 * "\x00\x00" // client capabilities
4916 * "\x00\x00\x01" // max packet
4917 * "haproxy\x00" // username (null terminated string)
4918 * "\x00" // filler (always 0x00)
4919 * "\x01\x00\x00" // packet length
4920 * "\x00" // packet number
4921 * "\x01" // COM_QUIT command
4922 * };
4923 */
4924
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004925 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4926 * const char mysql41_client_auth_pkt[] = {
4927 * "\x0e\x00\x00\" // packet length
4928 * "\x01" // packet number
4929 * "\x00\x00\x00\x00" // client capabilities
4930 * "\x00\x00\x00\x01" // max packet
4931 * "\x21" // character set (UTF-8)
4932 * char[23] // All zeroes
4933 * "haproxy\x00" // username (null terminated string)
4934 * "\x00" // filler (always 0x00)
4935 * "\x01\x00\x00" // packet length
4936 * "\x00" // packet number
4937 * "\x01" // COM_QUIT command
4938 * };
4939 */
4940
4941
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004942 if (*(args[2])) {
4943 int cur_arg = 2;
4944
4945 while (*(args[cur_arg])) {
4946 if (strcmp(args[cur_arg], "user") == 0) {
4947 char *mysqluser;
4948 int packetlen, reqlen, userlen;
4949
4950 /* suboption header - needs additional argument for it */
4951 if (*(args[cur_arg+1]) == 0) {
4952 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4953 file, linenum, args[0], args[1], args[cur_arg]);
4954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
4956 }
4957 mysqluser = args[cur_arg + 1];
4958 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004959
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004960 if (*(args[cur_arg+2])) {
4961 if (!strcmp(args[cur_arg+2], "post-41")) {
4962 packetlen = userlen + 7 + 27;
4963 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004964
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004965 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004966 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004967 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004968
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004969 snprintf(curproxy->check_req, 4, "%c%c%c",
4970 ((unsigned char) packetlen & 0xff),
4971 ((unsigned char) (packetlen >> 8) & 0xff),
4972 ((unsigned char) (packetlen >> 16) & 0xff));
4973
4974 curproxy->check_req[3] = 1;
4975 curproxy->check_req[5] = 130;
4976 curproxy->check_req[11] = 1;
4977 curproxy->check_req[12] = 33;
4978 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4979 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4980 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4981 cur_arg += 3;
4982 } else {
4983 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
4987 } else {
4988 packetlen = userlen + 7;
4989 reqlen = packetlen + 9;
4990
4991 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004992 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004993 curproxy->check_len = reqlen;
4994
4995 snprintf(curproxy->check_req, 4, "%c%c%c",
4996 ((unsigned char) packetlen & 0xff),
4997 ((unsigned char) (packetlen >> 8) & 0xff),
4998 ((unsigned char) (packetlen >> 16) & 0xff));
4999
5000 curproxy->check_req[3] = 1;
5001 curproxy->check_req[5] = 128;
5002 curproxy->check_req[8] = 1;
5003 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5004 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5005 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5006 cur_arg += 2;
5007 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005008 } else {
5009 /* unknown suboption - catchall */
5010 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5011 file, linenum, args[0], args[1]);
5012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
5014 }
5015 } /* end while loop */
5016 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005017 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005018 else if (!strcmp(args[1], "ldap-check")) {
5019 /* use LDAP request to check servers' health */
5020 free(curproxy->check_req);
5021 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005022 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005023 curproxy->options2 |= PR_O2_LDAP_CHK;
5024
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005025 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005026 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5027 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005028 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5029 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005030 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005031 else if (!strcmp(args[1], "spop-check")) {
5032 if (curproxy == &defproxy) {
5033 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5034 file, linenum, args[0], args[1]);
5035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
5037 }
5038 if (curproxy->cap & PR_CAP_FE) {
5039 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5040 file, linenum, args[0], args[1]);
5041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
5043 }
5044
5045 /* use SPOE request to check servers' health */
5046 free(curproxy->check_req);
5047 curproxy->check_req = NULL;
5048 curproxy->options2 &= ~PR_O2_CHK_ANY;
5049 curproxy->options2 |= PR_O2_SPOP_CHK;
5050
Christopher Faulet8ef75252017-02-20 22:56:03 +01005051 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005052 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
5055 }
5056 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5057 goto out;
5058 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005059 else if (!strcmp(args[1], "tcp-check")) {
5060 /* use raw TCPCHK send/expect to check servers' health */
5061 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5062 err_code |= ERR_WARN;
5063
5064 free(curproxy->check_req);
5065 curproxy->check_req = NULL;
5066 curproxy->options2 &= ~PR_O2_CHK_ANY;
5067 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005068 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5069 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005070 }
Simon Horman98637e52014-06-20 12:30:16 +09005071 else if (!strcmp(args[1], "external-check")) {
5072 /* excute an external command to check servers' health */
5073 free(curproxy->check_req);
5074 curproxy->check_req = NULL;
5075 curproxy->options2 &= ~PR_O2_CHK_ANY;
5076 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005077 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5078 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005079 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005080 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005081 int cur_arg;
5082
5083 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5084 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005085 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005086
Willy Tarreau87cf5142011-08-19 22:57:24 +02005087 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005088
5089 free(curproxy->fwdfor_hdr_name);
5090 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5091 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5092
5093 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5094 cur_arg = 2;
5095 while (*(args[cur_arg])) {
5096 if (!strcmp(args[cur_arg], "except")) {
5097 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005098 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005099 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5100 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005103 }
5104 /* flush useless bits */
5105 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005106 cur_arg += 2;
5107 } else if (!strcmp(args[cur_arg], "header")) {
5108 /* suboption header - needs additional argument for it */
5109 if (*(args[cur_arg+1]) == 0) {
5110 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5111 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005114 }
5115 free(curproxy->fwdfor_hdr_name);
5116 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5117 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5118 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005119 } else if (!strcmp(args[cur_arg], "if-none")) {
5120 curproxy->options &= ~PR_O_FF_ALWAYS;
5121 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005122 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005123 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005124 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005125 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005128 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005129 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005130 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005131 else if (!strcmp(args[1], "originalto")) {
5132 int cur_arg;
5133
5134 /* insert x-original-to field, but not for the IP address listed as an except.
5135 * set default options (ie: bitfield, header name, etc)
5136 */
5137
5138 curproxy->options |= PR_O_ORGTO;
5139
5140 free(curproxy->orgto_hdr_name);
5141 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5142 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5143
Willy Tarreau87cf5142011-08-19 22:57:24 +02005144 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005145 cur_arg = 2;
5146 while (*(args[cur_arg])) {
5147 if (!strcmp(args[cur_arg], "except")) {
5148 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005149 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 +02005150 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5151 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005154 }
5155 /* flush useless bits */
5156 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5157 cur_arg += 2;
5158 } else if (!strcmp(args[cur_arg], "header")) {
5159 /* suboption header - needs additional argument for it */
5160 if (*(args[cur_arg+1]) == 0) {
5161 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5162 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005165 }
5166 free(curproxy->orgto_hdr_name);
5167 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5168 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5169 cur_arg += 2;
5170 } else {
5171 /* unknown suboption - catchall */
5172 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5173 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005176 }
5177 } /* end while loop */
5178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 else {
5180 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
Willy Tarreau93893792009-07-23 13:19:11 +02005184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005186 else if (!strcmp(args[0], "default_backend")) {
5187 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005188 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005189
5190 if (*(args[1]) == 0) {
5191 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005194 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005195 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005196 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005197
5198 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5199 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005202 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005204
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005205 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5206 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 +01005207 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005208 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 /* enable reconnections to dispatch */
5210 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005211
5212 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005215 else if (!strcmp(args[0], "http-reuse")) {
5216 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5217 err_code |= ERR_WARN;
5218
5219 if (strcmp(args[1], "never") == 0) {
5220 /* enable a graceful server shutdown on an HTTP 404 response */
5221 curproxy->options &= ~PR_O_REUSE_MASK;
5222 curproxy->options |= PR_O_REUSE_NEVR;
5223 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5224 goto out;
5225 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005226 else if (strcmp(args[1], "safe") == 0) {
5227 /* enable a graceful server shutdown on an HTTP 404 response */
5228 curproxy->options &= ~PR_O_REUSE_MASK;
5229 curproxy->options |= PR_O_REUSE_SAFE;
5230 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5231 goto out;
5232 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005233 else if (strcmp(args[1], "aggressive") == 0) {
5234 curproxy->options &= ~PR_O_REUSE_MASK;
5235 curproxy->options |= PR_O_REUSE_AGGR;
5236 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5237 goto out;
5238 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005239 else if (strcmp(args[1], "always") == 0) {
5240 /* enable a graceful server shutdown on an HTTP 404 response */
5241 curproxy->options &= ~PR_O_REUSE_MASK;
5242 curproxy->options |= PR_O_REUSE_ALWS;
5243 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5244 goto out;
5245 }
5246 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005247 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005252 else if (!strcmp(args[0], "http-check")) {
5253 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005254 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005255
5256 if (strcmp(args[1], "disable-on-404") == 0) {
5257 /* enable a graceful server shutdown on an HTTP 404 response */
5258 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005259 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5260 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005261 }
Willy Tarreauef781042010-01-27 11:53:01 +01005262 else if (strcmp(args[1], "send-state") == 0) {
5263 /* enable emission of the apparent state of a server in HTTP checks */
5264 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005265 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5266 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005267 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005268 else if (strcmp(args[1], "expect") == 0) {
5269 const char *ptr_arg;
5270 int cur_arg;
5271
5272 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5273 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5274 err_code |= ERR_ALERT | ERR_FATAL;
5275 goto out;
5276 }
5277
5278 cur_arg = 2;
5279 /* consider exclamation marks, sole or at the beginning of a word */
5280 while (*(ptr_arg = args[cur_arg])) {
5281 while (*ptr_arg == '!') {
5282 curproxy->options2 ^= PR_O2_EXP_INV;
5283 ptr_arg++;
5284 }
5285 if (*ptr_arg)
5286 break;
5287 cur_arg++;
5288 }
5289 /* now ptr_arg points to the beginning of a word past any possible
5290 * exclamation mark, and cur_arg is the argument which holds this word.
5291 */
5292 if (strcmp(ptr_arg, "status") == 0) {
5293 if (!*(args[cur_arg + 1])) {
5294 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5295 file, linenum, args[0], args[1], ptr_arg);
5296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
5298 }
5299 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005300 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005301 curproxy->expect_str = strdup(args[cur_arg + 1]);
5302 }
5303 else if (strcmp(ptr_arg, "string") == 0) {
5304 if (!*(args[cur_arg + 1])) {
5305 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5306 file, linenum, args[0], args[1], ptr_arg);
5307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
5310 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005311 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005312 curproxy->expect_str = strdup(args[cur_arg + 1]);
5313 }
5314 else if (strcmp(ptr_arg, "rstatus") == 0) {
5315 if (!*(args[cur_arg + 1])) {
5316 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5317 file, linenum, args[0], args[1], ptr_arg);
5318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
5320 }
5321 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005322 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005323 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005324 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005325 free(curproxy->expect_regex);
5326 curproxy->expect_regex = NULL;
5327 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005328 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005329 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5330 error = NULL;
5331 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5332 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5333 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5334 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
5338 }
5339 else if (strcmp(ptr_arg, "rstring") == 0) {
5340 if (!*(args[cur_arg + 1])) {
5341 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5342 file, linenum, args[0], args[1], ptr_arg);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005347 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005348 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005349 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005350 free(curproxy->expect_regex);
5351 curproxy->expect_regex = NULL;
5352 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005353 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005354 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5355 error = NULL;
5356 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5357 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5358 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5359 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005360 err_code |= ERR_ALERT | ERR_FATAL;
5361 goto out;
5362 }
5363 }
5364 else {
5365 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5366 file, linenum, args[0], args[1], ptr_arg);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005371 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005372 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 +02005373 err_code |= ERR_ALERT | ERR_FATAL;
5374 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005375 }
5376 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005377 else if (!strcmp(args[0], "tcp-check")) {
5378 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5379 err_code |= ERR_WARN;
5380
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005381 if (strcmp(args[1], "comment") == 0) {
5382 int cur_arg;
5383 struct tcpcheck_rule *tcpcheck;
5384
5385 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005386 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005387 tcpcheck->action = TCPCHK_ACT_COMMENT;
5388
5389 if (!*args[cur_arg + 1]) {
5390 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5391 file, linenum, args[cur_arg]);
5392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 }
5395
5396 tcpcheck->comment = strdup(args[cur_arg + 1]);
5397
5398 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005399 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5400 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005401 }
5402 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005403 const char *ptr_arg;
5404 int cur_arg;
5405 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005406
5407 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005408 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5409 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5410 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5411 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5412 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005413
Willy Tarreau5581c272015-05-13 12:24:53 +02005414 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5415 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5416 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5417 file, linenum);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005420 }
5421
5422 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005423 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005424 tcpcheck->action = TCPCHK_ACT_CONNECT;
5425
5426 /* parsing each parameters to fill up the rule */
5427 while (*(ptr_arg = args[cur_arg])) {
5428 /* tcp port */
5429 if (strcmp(args[cur_arg], "port") == 0) {
5430 if ( (atol(args[cur_arg + 1]) > 65535) ||
5431 (atol(args[cur_arg + 1]) < 1) ){
5432 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5433 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
5437 tcpcheck->port = atol(args[cur_arg + 1]);
5438 cur_arg += 2;
5439 }
5440 /* send proxy protocol */
5441 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5442 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5443 cur_arg++;
5444 }
5445#ifdef USE_OPENSSL
5446 else if (strcmp(args[cur_arg], "ssl") == 0) {
5447 curproxy->options |= PR_O_TCPCHK_SSL;
5448 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5449 cur_arg++;
5450 }
5451#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005452 /* comment for this tcpcheck line */
5453 else if (strcmp(args[cur_arg], "comment") == 0) {
5454 if (!*args[cur_arg + 1]) {
5455 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5456 file, linenum, args[cur_arg]);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
5460 tcpcheck->comment = strdup(args[cur_arg + 1]);
5461 cur_arg += 2;
5462 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005463 else {
5464#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005465 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 +01005466#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005467 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 +01005468#endif /* USE_OPENSSL */
5469 file, linenum, args[0], args[1], args[cur_arg]);
5470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
5472 }
5473
5474 }
5475
5476 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5477 }
5478 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005479 if (! *(args[2]) ) {
5480 /* SEND string expected */
5481 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5482 file, linenum, args[0], args[1], args[2]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 } else {
5486 struct tcpcheck_rule *tcpcheck;
5487
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005488 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005489
5490 tcpcheck->action = TCPCHK_ACT_SEND;
5491 tcpcheck->string_len = strlen(args[2]);
5492 tcpcheck->string = strdup(args[2]);
5493 tcpcheck->expect_regex = NULL;
5494
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005495 /* comment for this tcpcheck line */
5496 if (strcmp(args[3], "comment") == 0) {
5497 if (!*args[4]) {
5498 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5499 file, linenum, args[3]);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 tcpcheck->comment = strdup(args[4]);
5504 }
5505
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005506 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5507 }
5508 }
5509 else if (strcmp(args[1], "send-binary") == 0) {
5510 if (! *(args[2]) ) {
5511 /* SEND binary string expected */
5512 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5513 file, linenum, args[0], args[1], args[2]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 } else {
5517 struct tcpcheck_rule *tcpcheck;
5518 char *err = NULL;
5519
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005520 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005521
5522 tcpcheck->action = TCPCHK_ACT_SEND;
5523 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5524 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5525 file, linenum, args[0], args[1], args[2], err);
5526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
5528 }
5529 tcpcheck->expect_regex = NULL;
5530
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005531 /* comment for this tcpcheck line */
5532 if (strcmp(args[3], "comment") == 0) {
5533 if (!*args[4]) {
5534 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5535 file, linenum, args[3]);
5536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
5538 }
5539 tcpcheck->comment = strdup(args[4]);
5540 }
5541
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005542 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5543 }
5544 }
5545 else if (strcmp(args[1], "expect") == 0) {
5546 const char *ptr_arg;
5547 int cur_arg;
5548 int inverse = 0;
5549
5550 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5551 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
5554 }
5555
5556 cur_arg = 2;
5557 /* consider exclamation marks, sole or at the beginning of a word */
5558 while (*(ptr_arg = args[cur_arg])) {
5559 while (*ptr_arg == '!') {
5560 inverse = !inverse;
5561 ptr_arg++;
5562 }
5563 if (*ptr_arg)
5564 break;
5565 cur_arg++;
5566 }
5567 /* now ptr_arg points to the beginning of a word past any possible
5568 * exclamation mark, and cur_arg is the argument which holds this word.
5569 */
5570 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005571 struct tcpcheck_rule *tcpcheck;
5572 char *err = NULL;
5573
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005574 if (!*(args[cur_arg + 1])) {
5575 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5576 file, linenum, args[0], args[1], ptr_arg);
5577 err_code |= ERR_ALERT | ERR_FATAL;
5578 goto out;
5579 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005581 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005582
5583 tcpcheck->action = TCPCHK_ACT_EXPECT;
5584 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5585 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5586 file, linenum, args[0], args[1], args[2], err);
5587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
5589 }
5590 tcpcheck->expect_regex = NULL;
5591 tcpcheck->inverse = inverse;
5592
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005593 /* tcpcheck comment */
5594 cur_arg += 2;
5595 if (strcmp(args[cur_arg], "comment") == 0) {
5596 if (!*args[cur_arg + 1]) {
5597 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5598 file, linenum, args[cur_arg + 1]);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
5602 tcpcheck->comment = strdup(args[cur_arg + 1]);
5603 }
5604
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005605 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5606 }
5607 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005608 struct tcpcheck_rule *tcpcheck;
5609
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005610 if (!*(args[cur_arg + 1])) {
5611 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5612 file, linenum, args[0], args[1], ptr_arg);
5613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
5615 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005616
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005617 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005618
5619 tcpcheck->action = TCPCHK_ACT_EXPECT;
5620 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5621 tcpcheck->string = strdup(args[cur_arg + 1]);
5622 tcpcheck->expect_regex = NULL;
5623 tcpcheck->inverse = inverse;
5624
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005625 /* tcpcheck comment */
5626 cur_arg += 2;
5627 if (strcmp(args[cur_arg], "comment") == 0) {
5628 if (!*args[cur_arg + 1]) {
5629 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5630 file, linenum, args[cur_arg + 1]);
5631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
5633 }
5634 tcpcheck->comment = strdup(args[cur_arg + 1]);
5635 }
5636
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005637 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5638 }
5639 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005640 struct tcpcheck_rule *tcpcheck;
5641
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005642 if (!*(args[cur_arg + 1])) {
5643 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5644 file, linenum, args[0], args[1], ptr_arg);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005648
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005649 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005650
5651 tcpcheck->action = TCPCHK_ACT_EXPECT;
5652 tcpcheck->string_len = 0;
5653 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005654 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5655 error = NULL;
5656 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5657 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5658 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5659 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663 tcpcheck->inverse = inverse;
5664
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005665 /* tcpcheck comment */
5666 cur_arg += 2;
5667 if (strcmp(args[cur_arg], "comment") == 0) {
5668 if (!*args[cur_arg + 1]) {
5669 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5670 file, linenum, args[cur_arg + 1]);
5671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
5673 }
5674 tcpcheck->comment = strdup(args[cur_arg + 1]);
5675 }
5676
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005677 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5678 }
5679 else {
5680 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5681 file, linenum, args[0], args[1], ptr_arg);
5682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
5684 }
5685 }
5686 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005687 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
5691 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005692 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005693 if (curproxy == &defproxy) {
5694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005695 err_code |= ERR_ALERT | ERR_FATAL;
5696 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005697 }
5698
Willy Tarreaub80c2302007-11-30 20:51:32 +01005699 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005700 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005701
5702 if (strcmp(args[1], "fail") == 0) {
5703 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005704 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005705 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5706 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005709 }
5710
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005711 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005712 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5713 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005714 err_code |= ERR_ALERT | ERR_FATAL;
5715 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005716 }
5717 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5718 }
5719 else {
5720 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005723 }
5724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725#ifdef TPROXY
5726 else if (!strcmp(args[0], "transparent")) {
5727 /* enable transparent proxy connections */
5728 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005729 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 }
5732#endif
5733 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005734 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005735 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005736
Willy Tarreaubaaee002006-06-26 02:48:02 +02005737 if (*(args[1]) == 0) {
5738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005739 err_code |= ERR_ALERT | ERR_FATAL;
5740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 }
5742 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005743 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005746 else if (!strcmp(args[0], "backlog")) { /* backlog */
5747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005749
5750 if (*(args[1]) == 0) {
5751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005752 err_code |= ERR_ALERT | ERR_FATAL;
5753 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005754 }
5755 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005756 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5757 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005758 }
Willy Tarreau86034312006-12-29 00:10:33 +01005759 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005762
Willy Tarreau86034312006-12-29 00:10:33 +01005763 if (*(args[1]) == 0) {
5764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005765 err_code |= ERR_ALERT | ERR_FATAL;
5766 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005767 }
5768 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005769 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5770 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5773 if (*(args[1]) == 0) {
5774 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005775 err_code |= ERR_ALERT | ERR_FATAL;
5776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005778 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5779 if (err) {
5780 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5781 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005784 }
5785 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005786 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 }
5789 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005790 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005791 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005792 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005793
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 if (curproxy == &defproxy) {
5795 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005799 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005800 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005801
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005802 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005803 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005804 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005805 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005806 goto out;
5807 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005808
5809 proto = protocol_by_family(sk->ss_family);
5810 if (!proto || !proto->connect) {
5811 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5812 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005813 err_code |= ERR_ALERT | ERR_FATAL;
5814 goto out;
5815 }
5816
5817 if (port1 != port2) {
5818 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5819 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005820 err_code |= ERR_ALERT | ERR_FATAL;
5821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005823
5824 if (!port1) {
5825 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5826 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
5829 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005830
William Lallemanddf1425a2015-04-28 20:17:49 +02005831 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5832 goto out;
5833
Willy Tarreaud5191e72010-02-09 20:50:45 +01005834 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005835 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 }
5837 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005840
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005841 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5842 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005847 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005848 /**
5849 * The syntax for hash-type config element is
5850 * hash-type {map-based|consistent} [[<algo>] avalanche]
5851 *
5852 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5853 */
5854 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005855
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005856 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5857 err_code |= ERR_WARN;
5858
5859 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005860 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5861 }
5862 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005863 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5864 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005865 else if (strcmp(args[1], "avalanche") == 0) {
5866 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]);
5867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005869 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005870 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005871 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005872 err_code |= ERR_ALERT | ERR_FATAL;
5873 goto out;
5874 }
Bhaskar98634f02013-10-29 23:30:51 -04005875
5876 /* set the hash function to use */
5877 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005878 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005879 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005880
5881 /* if consistent with no argument, then avalanche modifier is also applied */
5882 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5883 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005884 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005885 /* set the hash function */
5886 if (!strcmp(args[2], "sdbm")) {
5887 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5888 }
5889 else if (!strcmp(args[2], "djb2")) {
5890 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005891 }
5892 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005893 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005894 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005895 else if (!strcmp(args[2], "crc32")) {
5896 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5897 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005898 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005899 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 -05005900 err_code |= ERR_ALERT | ERR_FATAL;
5901 goto out;
5902 }
5903
5904 /* set the hash modifier */
5905 if (!strcmp(args[3], "avalanche")) {
5906 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5907 }
5908 else if (*args[3]) {
5909 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
5912 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005913 }
William Lallemanda73203e2012-03-12 12:48:57 +01005914 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005915 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5916 if (*(args[1]) == 0) {
5917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5918 err_code |= ERR_ALERT | ERR_FATAL;
5919 goto out;
5920 }
5921 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5922 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5923 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5924 err_code |= ERR_ALERT | ERR_FATAL;
5925 goto out;
5926 }
5927 }
William Lallemanda73203e2012-03-12 12:48:57 +01005928 else if (strcmp(args[0], "unique-id-format") == 0) {
5929 if (!*(args[1])) {
5930 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5931 err_code |= ERR_ALERT | ERR_FATAL;
5932 goto out;
5933 }
William Lallemand3203ff42012-11-11 17:30:56 +01005934 if (*(args[2])) {
5935 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5936 err_code |= ERR_ALERT | ERR_FATAL;
5937 goto out;
5938 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005939 free(curproxy->conf.uniqueid_format_string);
5940 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005941
Willy Tarreau62a61232013-04-12 18:13:46 +02005942 free(curproxy->conf.uif_file);
5943 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5944 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005945 }
William Lallemanda73203e2012-03-12 12:48:57 +01005946
5947 else if (strcmp(args[0], "unique-id-header") == 0) {
5948 if (!*(args[1])) {
5949 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5950 err_code |= ERR_ALERT | ERR_FATAL;
5951 goto out;
5952 }
5953 free(curproxy->header_unique_id);
5954 curproxy->header_unique_id = strdup(args[1]);
5955 }
5956
William Lallemand723b73a2012-02-08 16:37:49 +01005957 else if (strcmp(args[0], "log-format") == 0) {
5958 if (!*(args[1])) {
5959 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5960 err_code |= ERR_ALERT | ERR_FATAL;
5961 goto out;
5962 }
William Lallemand3203ff42012-11-11 17:30:56 +01005963 if (*(args[2])) {
5964 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5965 err_code |= ERR_ALERT | ERR_FATAL;
5966 goto out;
5967 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005968 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5969 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005970
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005971 if (curproxy->conf.logformat_string == default_http_log_format)
5972 oldlogformat = "option httplog";
5973 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5974 oldlogformat = "option tcplog";
5975 else if (curproxy->conf.logformat_string == clf_http_log_format)
5976 oldlogformat = "option httplog clf";
5977 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5978 file, linenum, oldlogformat);
5979 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005980 if (curproxy->conf.logformat_string != default_http_log_format &&
5981 curproxy->conf.logformat_string != default_tcp_log_format &&
5982 curproxy->conf.logformat_string != clf_http_log_format)
5983 free(curproxy->conf.logformat_string);
5984 curproxy->conf.logformat_string = strdup(args[1]);
5985
5986 free(curproxy->conf.lfs_file);
5987 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5988 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005989
5990 /* get a chance to improve log-format error reporting by
5991 * reporting the correct line-number when possible.
5992 */
5993 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5994 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5995 file, linenum, curproxy->id);
5996 err_code |= ERR_WARN;
5997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005999 else if (!strcmp(args[0], "log-format-sd")) {
6000 if (!*(args[1])) {
6001 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6002 err_code |= ERR_ALERT | ERR_FATAL;
6003 goto out;
6004 }
6005 if (*(args[2])) {
6006 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
6009 }
6010
6011 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6012 free(curproxy->conf.logformat_sd_string);
6013 curproxy->conf.logformat_sd_string = strdup(args[1]);
6014
6015 free(curproxy->conf.lfsd_file);
6016 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6017 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6018
6019 /* get a chance to improve log-format-sd error reporting by
6020 * reporting the correct line-number when possible.
6021 */
6022 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6023 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6024 file, linenum, curproxy->id);
6025 err_code |= ERR_WARN;
6026 }
6027 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006028 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6029 if (*(args[1]) == 0) {
6030 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6031 err_code |= ERR_ALERT | ERR_FATAL;
6032 goto out;
6033 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006034 chunk_destroy(&curproxy->log_tag);
6035 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006036 }
William Lallemand0f99e342011-10-12 17:50:54 +02006037 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6038 /* delete previous herited or defined syslog servers */
6039 struct logsrv *back;
6040
6041 if (*(args[1]) != 0) {
6042 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6043 err_code |= ERR_ALERT | ERR_FATAL;
6044 goto out;
6045 }
6046
William Lallemand723b73a2012-02-08 16:37:49 +01006047 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6048 LIST_DEL(&tmplogsrv->list);
6049 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006050 }
6051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006053 struct logsrv *logsrv;
6054
Willy Tarreaubaaee002006-06-26 02:48:02 +02006055 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006056 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006057 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006058 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006059 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006060 LIST_INIT(&node->list);
6061 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063 }
6064 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006065 struct sockaddr_storage *sk;
6066 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006067 int arg = 0;
6068 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006069
Vincent Bernat02779b62016-04-03 13:48:43 +02006070 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006071
Willy Tarreau18324f52014-06-27 18:10:07 +02006072 /* just after the address, a length may be specified */
6073 if (strcmp(args[arg+2], "len") == 0) {
6074 len = atoi(args[arg+3]);
6075 if (len < 80 || len > 65535) {
6076 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6077 file, linenum, args[arg+3]);
6078 err_code |= ERR_ALERT | ERR_FATAL;
6079 goto out;
6080 }
6081 logsrv->maxlen = len;
6082
6083 /* skip these two args */
6084 arg += 2;
6085 }
6086 else
6087 logsrv->maxlen = MAX_SYSLOG_LEN;
6088
Christopher Faulet084aa962017-08-29 16:54:41 +02006089 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006090 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006091
Dragan Dosen1322d092015-09-22 16:05:32 +02006092 /* after the length, a format may be specified */
6093 if (strcmp(args[arg+2], "format") == 0) {
6094 logsrv->format = get_log_format(args[arg+3]);
6095 if (logsrv->format < 0) {
6096 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6097 err_code |= ERR_ALERT | ERR_FATAL;
6098 goto out;
6099 }
6100
6101 /* skip these two args */
6102 arg += 2;
6103 }
6104
William Lallemanddf1425a2015-04-28 20:17:49 +02006105 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6106 goto out;
6107
Willy Tarreau18324f52014-06-27 18:10:07 +02006108 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006109 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006110 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006111 err_code |= ERR_ALERT | ERR_FATAL;
6112 goto out;
6113
Willy Tarreaubaaee002006-06-26 02:48:02 +02006114 }
6115
William Lallemand0f99e342011-10-12 17:50:54 +02006116 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006117 if (*(args[arg+3])) {
6118 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006119 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006120 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006121 err_code |= ERR_ALERT | ERR_FATAL;
6122 goto out;
6123
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124 }
6125 }
6126
William Lallemand0f99e342011-10-12 17:50:54 +02006127 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006128 if (*(args[arg+4])) {
6129 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006130 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006131 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006132 err_code |= ERR_ALERT | ERR_FATAL;
6133 goto out;
6134
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006135 }
6136 }
6137
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006138 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006139 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006140 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006141 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006142 goto out;
6143 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006144
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006145 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006146
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006147 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006148 if (port1 != port2) {
6149 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6150 file, linenum, args[0], args[1]);
6151 err_code |= ERR_ALERT | ERR_FATAL;
6152 goto out;
6153 }
6154
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006155 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006156 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 }
William Lallemand0f99e342011-10-12 17:50:54 +02006158
6159 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 }
6161 else {
6162 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6163 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006164 err_code |= ERR_ALERT | ERR_FATAL;
6165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 }
6167 }
6168 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006169 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006170 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006171 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006172 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006173
Willy Tarreau977b8e42006-12-29 14:19:17 +01006174 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006175 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006176
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006178 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6179 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006180 err_code |= ERR_ALERT | ERR_FATAL;
6181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006183
6184 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006185 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6186 free(curproxy->conn_src.iface_name);
6187 curproxy->conn_src.iface_name = NULL;
6188 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006189
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006190 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006191 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006192 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006193 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006194 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006195 goto out;
6196 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006197
6198 proto = protocol_by_family(sk->ss_family);
6199 if (!proto || !proto->connect) {
6200 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006201 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006202 err_code |= ERR_ALERT | ERR_FATAL;
6203 goto out;
6204 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006205
6206 if (port1 != port2) {
6207 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6208 file, linenum, args[0], args[1]);
6209 err_code |= ERR_ALERT | ERR_FATAL;
6210 goto out;
6211 }
6212
Willy Tarreauef9a3602012-12-08 22:29:20 +01006213 curproxy->conn_src.source_addr = *sk;
6214 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006215
6216 cur_arg = 2;
6217 while (*(args[cur_arg])) {
6218 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006219#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006220 if (!*args[cur_arg + 1]) {
6221 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6222 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006223 err_code |= ERR_ALERT | ERR_FATAL;
6224 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006225 }
6226
6227 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006228 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6229 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006230 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006231 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6232 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006233 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6234 char *name, *end;
6235
6236 name = args[cur_arg+1] + 7;
6237 while (isspace(*name))
6238 name++;
6239
6240 end = name;
6241 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6242 end++;
6243
Willy Tarreauef9a3602012-12-08 22:29:20 +01006244 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6245 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6246 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6247 curproxy->conn_src.bind_hdr_len = end - name;
6248 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6249 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6250 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006251
6252 /* now look for an occurrence number */
6253 while (isspace(*end))
6254 end++;
6255 if (*end == ',') {
6256 end++;
6257 name = end;
6258 if (*end == '-')
6259 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006260 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006261 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006262 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006263 }
6264
Willy Tarreauef9a3602012-12-08 22:29:20 +01006265 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006266 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6267 " occurrences values smaller than %d.\n",
6268 file, linenum, MAX_HDR_HISTORY);
6269 err_code |= ERR_ALERT | ERR_FATAL;
6270 goto out;
6271 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006272 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006273 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006274
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006275 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006276 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006277 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006278 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006279 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006280 goto out;
6281 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006282
6283 proto = protocol_by_family(sk->ss_family);
6284 if (!proto || !proto->connect) {
6285 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6286 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006287 err_code |= ERR_ALERT | ERR_FATAL;
6288 goto out;
6289 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006290
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006291 if (port1 != port2) {
6292 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6293 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006294 err_code |= ERR_ALERT | ERR_FATAL;
6295 goto out;
6296 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006297 curproxy->conn_src.tproxy_addr = *sk;
6298 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006299 }
6300 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006301#else /* no TPROXY support */
6302 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006303 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006304 err_code |= ERR_ALERT | ERR_FATAL;
6305 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006306#endif
6307 cur_arg += 2;
6308 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006309 }
6310
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006311 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6312#ifdef SO_BINDTODEVICE
6313 if (!*args[cur_arg + 1]) {
6314 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6315 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006316 err_code |= ERR_ALERT | ERR_FATAL;
6317 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006318 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006319 free(curproxy->conn_src.iface_name);
6320 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6321 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006322 global.last_checks |= LSTCHK_NETADM;
6323#else
6324 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6325 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006326 err_code |= ERR_ALERT | ERR_FATAL;
6327 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006328#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006329 cur_arg += 2;
6330 continue;
6331 }
6332 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006333 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006334 err_code |= ERR_ALERT | ERR_FATAL;
6335 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006338 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6339 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6340 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006341 err_code |= ERR_ALERT | ERR_FATAL;
6342 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006343 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006348 err_code |= ERR_ALERT | ERR_FATAL;
6349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351
6352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006353 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006354 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 }
6358 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006360 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
6365 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006367 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006371 }
6372 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006373 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006374 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006375 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006376 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378 }
6379 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006380 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006381 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006382 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006383 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006386 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006387 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006388 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006389 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006390 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006391 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006394 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6396 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006397 err_code |= ERR_ALERT | ERR_FATAL;
6398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006400
6401 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006402 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006403 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006404 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 }
6407 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006408 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006409 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006410 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006411 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
6414 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006415 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006416 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006417 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006418 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
6421 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006423 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006424 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006430 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006435 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006437 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006438 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006440 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006443 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006444
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445 if (curproxy == &defproxy) {
6446 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006447 err_code |= ERR_ALERT | ERR_FATAL;
6448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006450 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006451 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 if (*(args[1]) == 0) {
6454 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006455 err_code |= ERR_ALERT | ERR_FATAL;
6456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006457 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006458
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006459 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006460 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006461 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6462 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006463 err_code |= ERR_ALERT | ERR_FATAL;
6464 goto out;
6465 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006466 err_code |= warnif_cond_conflicts(cond,
6467 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6468 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006469 }
6470 else if (*args[2]) {
6471 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6472 file, linenum, args[0], args[2]);
6473 err_code |= ERR_ALERT | ERR_FATAL;
6474 goto out;
6475 }
6476
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006477 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006478 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006479 wl->s = strdup(args[1]);
6480 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006481 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 }
6483 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006484 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6486 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006487 err_code |= ERR_ALERT | ERR_FATAL;
6488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006489 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006490
Willy Tarreauade5ec42010-01-28 19:33:49 +01006491 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006492 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006493 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006494 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006496 }
6497 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006498 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006499 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006500 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006501 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 }
6504 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006505 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006506 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006507 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006508 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006510 }
6511 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006512 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6514 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006515 err_code |= ERR_ALERT | ERR_FATAL;
6516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517 }
6518
Willy Tarreauade5ec42010-01-28 19:33:49 +01006519 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006520 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006521 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006522 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524 }
6525 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006526 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006527 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006528 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006529 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006531 }
6532 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006533 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006534 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006535 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006536 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 }
6539 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006540 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006541
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 if (curproxy == &defproxy) {
6543 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006544 err_code |= ERR_ALERT | ERR_FATAL;
6545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006546 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006547 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006548 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550 if (*(args[1]) == 0) {
6551 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006552 err_code |= ERR_ALERT | ERR_FATAL;
6553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006554 }
6555
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006556 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006557 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006558 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6559 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006560 err_code |= ERR_ALERT | ERR_FATAL;
6561 goto out;
6562 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006563 err_code |= warnif_cond_conflicts(cond,
6564 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6565 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006566 }
6567 else if (*args[2]) {
6568 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6569 file, linenum, args[0], args[2]);
6570 err_code |= ERR_ALERT | ERR_FATAL;
6571 goto out;
6572 }
6573
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006574 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006575 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006576 wl->s = strdup(args[1]);
6577 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 }
6579 else if (!strcmp(args[0], "errorloc") ||
6580 !strcmp(args[0], "errorloc302") ||
6581 !strcmp(args[0], "errorloc303")) { /* error location */
6582 int errnum, errlen;
6583 char *err;
6584
Willy Tarreau977b8e42006-12-29 14:19:17 +01006585 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006586 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006587
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006589 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006590 err_code |= ERR_ALERT | ERR_FATAL;
6591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 }
6593
6594 errnum = atol(args[1]);
6595 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006596 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6597 err = malloc(errlen);
6598 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006600 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6601 err = malloc(errlen);
6602 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603 }
6604
Willy Tarreau0f772532006-12-23 20:51:41 +01006605 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6606 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006607 chunk_destroy(&curproxy->errmsg[rc]);
6608 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006609 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006612
6613 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006614 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6615 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 free(err);
6617 }
6618 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006619 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6620 int errnum, errlen, fd;
6621 char *err;
6622 struct stat stat;
6623
6624 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006625 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006626
6627 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006628 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006629 err_code |= ERR_ALERT | ERR_FATAL;
6630 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006631 }
6632
6633 fd = open(args[2], O_RDONLY);
6634 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6635 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6636 file, linenum, args[2], args[1]);
6637 if (fd >= 0)
6638 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006639 err_code |= ERR_ALERT | ERR_FATAL;
6640 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006641 }
6642
Willy Tarreau27a674e2009-08-17 07:23:33 +02006643 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006644 errlen = stat.st_size;
6645 } else {
6646 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006647 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006648 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006649 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006650 }
6651
6652 err = malloc(errlen); /* malloc() must succeed during parsing */
6653 errnum = read(fd, err, errlen);
6654 if (errnum != errlen) {
6655 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6656 file, linenum, args[2], args[1]);
6657 close(fd);
6658 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006659 err_code |= ERR_ALERT | ERR_FATAL;
6660 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006661 }
6662 close(fd);
6663
6664 errnum = atol(args[1]);
6665 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6666 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006667 chunk_destroy(&curproxy->errmsg[rc]);
6668 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006669 break;
6670 }
6671 }
6672
6673 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006674 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6675 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006676 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006677 free(err);
6678 }
6679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006680 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006681 struct cfg_kw_list *kwl;
6682 int index;
6683
6684 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6685 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6686 if (kwl->kw[index].section != CFG_LISTEN)
6687 continue;
6688 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6689 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006690 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006691 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006692 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006693 err_code |= ERR_ALERT | ERR_FATAL;
6694 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006695 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006696 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006697 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006698 err_code |= ERR_WARN;
6699 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006700 }
Willy Tarreau93893792009-07-23 13:19:11 +02006701 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006702 }
6703 }
6704 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006705
Willy Tarreau6daf3432008-01-22 16:44:08 +01006706 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006707 err_code |= ERR_ALERT | ERR_FATAL;
6708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006709 }
Willy Tarreau93893792009-07-23 13:19:11 +02006710 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006711 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006712 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006713}
6714
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006715int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006716cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6717{
6718#ifdef CONFIG_HAP_NS
6719 const char *err;
6720 const char *item = args[0];
6721
6722 if (!strcmp(item, "namespace_list")) {
6723 return 0;
6724 }
6725 else if (!strcmp(item, "namespace")) {
6726 size_t idx = 1;
6727 const char *current;
6728 while (*(current = args[idx++])) {
6729 err = invalid_char(current);
6730 if (err) {
6731 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6732 file, linenum, *err, item, current);
6733 return ERR_ALERT | ERR_FATAL;
6734 }
6735
6736 if (netns_store_lookup(current, strlen(current))) {
6737 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6738 file, linenum, current);
6739 return ERR_ALERT | ERR_FATAL;
6740 }
6741 if (!netns_store_insert(current)) {
6742 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6743 file, linenum, current);
6744 return ERR_ALERT | ERR_FATAL;
6745 }
6746 }
6747 }
6748
6749 return 0;
6750#else
6751 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6752 file, linenum);
6753 return ERR_ALERT | ERR_FATAL;
6754#endif
6755}
6756
6757int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006758cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6759{
6760
6761 int err_code = 0;
6762 const char *err;
6763
6764 if (!strcmp(args[0], "userlist")) { /* new userlist */
6765 struct userlist *newul;
6766
6767 if (!*args[1]) {
6768 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6769 file, linenum, args[0]);
6770 err_code |= ERR_ALERT | ERR_FATAL;
6771 goto out;
6772 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006773 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6774 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006775
6776 err = invalid_char(args[1]);
6777 if (err) {
6778 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6779 file, linenum, *err, args[0], args[1]);
6780 err_code |= ERR_ALERT | ERR_FATAL;
6781 goto out;
6782 }
6783
6784 for (newul = userlist; newul; newul = newul->next)
6785 if (!strcmp(newul->name, args[1])) {
6786 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6787 file, linenum, args[1]);
6788 err_code |= ERR_WARN;
6789 goto out;
6790 }
6791
Vincent Bernat02779b62016-04-03 13:48:43 +02006792 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006793 if (!newul) {
6794 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6795 err_code |= ERR_ALERT | ERR_ABORT;
6796 goto out;
6797 }
6798
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006799 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006800 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006801 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6802 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006803 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006804 goto out;
6805 }
6806
6807 newul->next = userlist;
6808 userlist = newul;
6809
6810 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006811 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006812 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006813 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006814
6815 if (!*args[1]) {
6816 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6817 file, linenum, args[0]);
6818 err_code |= ERR_ALERT | ERR_FATAL;
6819 goto out;
6820 }
6821
6822 err = invalid_char(args[1]);
6823 if (err) {
6824 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6825 file, linenum, *err, args[0], args[1]);
6826 err_code |= ERR_ALERT | ERR_FATAL;
6827 goto out;
6828 }
6829
William Lallemand4ac9f542015-05-28 18:03:51 +02006830 if (!userlist)
6831 goto out;
6832
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006833 for (ag = userlist->groups; ag; ag = ag->next)
6834 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006835 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6836 file, linenum, args[1], userlist->name);
6837 err_code |= ERR_ALERT;
6838 goto out;
6839 }
6840
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006841 ag = calloc(1, sizeof(*ag));
6842 if (!ag) {
6843 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6844 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006845 goto out;
6846 }
6847
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006848 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006849 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006850 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6851 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006852 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006853 goto out;
6854 }
6855
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006856 cur_arg = 2;
6857
6858 while (*args[cur_arg]) {
6859 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006860 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006861 cur_arg += 2;
6862 continue;
6863 } else {
6864 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6865 file, linenum, args[0]);
6866 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006867 free(ag->groupusers);
6868 free(ag->name);
6869 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006870 goto out;
6871 }
6872 }
6873
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006874 ag->next = userlist->groups;
6875 userlist->groups = ag;
6876
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006877 } else if (!strcmp(args[0], "user")) { /* new user */
6878 struct auth_users *newuser;
6879 int cur_arg;
6880
6881 if (!*args[1]) {
6882 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6883 file, linenum, args[0]);
6884 err_code |= ERR_ALERT | ERR_FATAL;
6885 goto out;
6886 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006887 if (!userlist)
6888 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006889
6890 for (newuser = userlist->users; newuser; newuser = newuser->next)
6891 if (!strcmp(newuser->user, args[1])) {
6892 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6893 file, linenum, args[1], userlist->name);
6894 err_code |= ERR_ALERT;
6895 goto out;
6896 }
6897
Vincent Bernat02779b62016-04-03 13:48:43 +02006898 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006899 if (!newuser) {
6900 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6901 err_code |= ERR_ALERT | ERR_ABORT;
6902 goto out;
6903 }
6904
6905 newuser->user = strdup(args[1]);
6906
6907 newuser->next = userlist->users;
6908 userlist->users = newuser;
6909
6910 cur_arg = 2;
6911
6912 while (*args[cur_arg]) {
6913 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006914#ifdef CONFIG_HAP_CRYPT
6915 if (!crypt("", args[cur_arg + 1])) {
6916 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6917 file, linenum, newuser->user);
6918 err_code |= ERR_ALERT | ERR_FATAL;
6919 goto out;
6920 }
6921#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006922 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6923 file, linenum);
6924 err_code |= ERR_ALERT;
6925#endif
6926 newuser->pass = strdup(args[cur_arg + 1]);
6927 cur_arg += 2;
6928 continue;
6929 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6930 newuser->pass = strdup(args[cur_arg + 1]);
6931 newuser->flags |= AU_O_INSECURE;
6932 cur_arg += 2;
6933 continue;
6934 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006935 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006936 cur_arg += 2;
6937 continue;
6938 } else {
6939 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6940 file, linenum, args[0]);
6941 err_code |= ERR_ALERT | ERR_FATAL;
6942 goto out;
6943 }
6944 }
6945 } else {
6946 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6947 err_code |= ERR_ALERT | ERR_FATAL;
6948 }
6949
6950out:
6951 return err_code;
6952}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006953
Christopher Faulet79bdef32016-11-04 22:36:15 +01006954int
6955cfg_parse_scope(const char *file, int linenum, char *line)
6956{
6957 char *beg, *end, *scope = NULL;
6958 int err_code = 0;
6959 const char *err;
6960
6961 beg = line + 1;
6962 end = strchr(beg, ']');
6963
6964 /* Detect end of scope declaration */
6965 if (!end || end == beg) {
6966 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6967 file, linenum);
6968 err_code |= ERR_ALERT | ERR_FATAL;
6969 goto out;
6970 }
6971
6972 /* Get scope name and check its validity */
6973 scope = my_strndup(beg, end-beg);
6974 err = invalid_char(scope);
6975 if (err) {
6976 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6977 file, linenum, *err);
6978 err_code |= ERR_ALERT | ERR_ABORT;
6979 goto out;
6980 }
6981
6982 /* Be sure to have a scope declaration alone on its line */
6983 line = end+1;
6984 while (isspace((unsigned char)*line))
6985 line++;
6986 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6987 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6988 file, linenum, *line);
6989 err_code |= ERR_ALERT | ERR_ABORT;
6990 goto out;
6991 }
6992
6993 /* We have a valid scope declaration, save it */
6994 free(cfg_scope);
6995 cfg_scope = scope;
6996 scope = NULL;
6997
6998 out:
6999 free(scope);
7000 return err_code;
7001}
7002
Willy Tarreaubaaee002006-06-26 02:48:02 +02007003/*
7004 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007005 * Returns the error code, 0 if OK, or any combination of :
7006 * - ERR_ABORT: must abort ASAP
7007 * - ERR_FATAL: we can continue parsing but not start the service
7008 * - ERR_WARN: a warning has been emitted
7009 * - ERR_ALERT: an alert has been emitted
7010 * Only the two first ones can stop processing, the two others are just
7011 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007012 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007013int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007014{
William Lallemand64e84512015-05-12 14:25:37 +02007015 char *thisline;
7016 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007017 FILE *f;
7018 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007019 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007020 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007021 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007022 int readbytes = 0;
7023
7024 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007025 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007026 return -1;
7027 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007028
David Carlier97880bb2016-04-08 10:35:26 +01007029 if ((f=fopen(file,"r")) == NULL) {
7030 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007031 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007033
William Lallemandb2f07452015-05-12 14:27:13 +02007034next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007035 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007036 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007037 char *end;
7038 char *args[MAX_LINE_ARGS + 1];
7039 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007040 int dquote = 0; /* double quote */
7041 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007042
Willy Tarreaubaaee002006-06-26 02:48:02 +02007043 linenum++;
7044
7045 end = line + strlen(line);
7046
William Lallemand64e84512015-05-12 14:25:37 +02007047 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007048 /* Check if we reached the limit and the last char is not \n.
7049 * Watch out for the last line without the terminating '\n'!
7050 */
William Lallemand64e84512015-05-12 14:25:37 +02007051 char *newline;
7052 int newlinesize = linesize * 2;
7053
7054 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7055 if (newline == NULL) {
7056 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7057 file, linenum);
7058 err_code |= ERR_ALERT | ERR_FATAL;
7059 continue;
7060 }
7061
7062 readbytes = linesize - 1;
7063 linesize = newlinesize;
7064 thisline = newline;
7065 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007066 }
7067
William Lallemand64e84512015-05-12 14:25:37 +02007068 readbytes = 0;
7069
Willy Tarreaubaaee002006-06-26 02:48:02 +02007070 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007071 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007072 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007073
Christopher Faulet79bdef32016-11-04 22:36:15 +01007074
7075 if (*line == '[') {/* This is the begining if a scope */
7076 err_code |= cfg_parse_scope(file, linenum, line);
7077 goto next_line;
7078 }
7079
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 arg = 0;
7081 args[arg] = line;
7082
7083 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007084 if (*line == '"' && !squote) { /* double quote outside single quotes */
7085 if (dquote)
7086 dquote = 0;
7087 else
7088 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007089 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007090 end--;
7091 }
7092 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7093 if (squote)
7094 squote = 0;
7095 else
7096 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007097 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007098 end--;
7099 }
7100 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7102 * C equivalent value. Other combinations left unchanged (eg: \1).
7103 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104 int skip = 0;
7105 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7106 *line = line[1];
7107 skip = 1;
7108 }
7109 else if (line[1] == 'r') {
7110 *line = '\r';
7111 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007113 else if (line[1] == 'n') {
7114 *line = '\n';
7115 skip = 1;
7116 }
7117 else if (line[1] == 't') {
7118 *line = '\t';
7119 skip = 1;
7120 }
7121 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007122 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123 unsigned char hex1, hex2;
7124 hex1 = toupper(line[2]) - '0';
7125 hex2 = toupper(line[3]) - '0';
7126 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7127 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7128 *line = (hex1<<4) + hex2;
7129 skip = 3;
7130 }
7131 else {
7132 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007133 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007134 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007135 } else if (line[1] == '"') {
7136 *line = '"';
7137 skip = 1;
7138 } else if (line[1] == '\'') {
7139 *line = '\'';
7140 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007141 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7142 *line = '$';
7143 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007144 }
7145 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007146 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007147 end -= skip;
7148 }
7149 line++;
7150 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007151 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007152 /* end of string, end of loop */
7153 *line = 0;
7154 break;
7155 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007156 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007158 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007159 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007160 line++;
7161 args[++arg] = line;
7162 }
William Lallemandb2f07452015-05-12 14:27:13 +02007163 else if (dquote && *line == '$') {
7164 /* environment variables are evaluated inside double quotes */
7165 char *var_beg;
7166 char *var_end;
7167 char save_char;
7168 char *value;
7169 int val_len;
7170 int newlinesize;
7171 int braces = 0;
7172
7173 var_beg = line + 1;
7174 var_end = var_beg;
7175
7176 if (*var_beg == '{') {
7177 var_beg++;
7178 var_end++;
7179 braces = 1;
7180 }
7181
7182 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7183 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7184 err_code |= ERR_ALERT | ERR_FATAL;
7185 goto next_line; /* skip current line */
7186 }
7187
7188 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7189 var_end++;
7190
7191 save_char = *var_end;
7192 *var_end = '\0';
7193 value = getenv(var_beg);
7194 *var_end = save_char;
7195 val_len = value ? strlen(value) : 0;
7196
7197 if (braces) {
7198 if (*var_end == '}') {
7199 var_end++;
7200 braces = 0;
7201 } else {
7202 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7203 err_code |= ERR_ALERT | ERR_FATAL;
7204 goto next_line; /* skip current line */
7205 }
7206 }
7207
7208 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7209
7210 /* if not enough space in thisline */
7211 if (newlinesize > linesize) {
7212 char *newline;
7213
7214 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7215 if (newline == NULL) {
7216 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7217 err_code |= ERR_ALERT | ERR_FATAL;
7218 goto next_line; /* slip current line */
7219 }
7220 /* recompute pointers if realloc returns a new pointer */
7221 if (newline != thisline) {
7222 int i;
7223 int diff;
7224
7225 for (i = 0; i <= arg; i++) {
7226 diff = args[i] - thisline;
7227 args[i] = newline + diff;
7228 }
7229
7230 diff = var_end - thisline;
7231 var_end = newline + diff;
7232 diff = end - thisline;
7233 end = newline + diff;
7234 diff = line - thisline;
7235 line = newline + diff;
7236 thisline = newline;
7237 }
7238 linesize = newlinesize;
7239 }
7240
7241 /* insert value inside the line */
7242 memmove(line + val_len, var_end, end - var_end + 1);
7243 memcpy(line, value, val_len);
7244 end += val_len - (var_end - line);
7245 line += val_len;
7246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 else {
7248 line++;
7249 }
7250 }
William Lallemandb2f07452015-05-12 14:27:13 +02007251
William Lallemandf9873ba2015-05-05 17:37:14 +02007252 if (dquote) {
7253 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7254 err_code |= ERR_ALERT | ERR_FATAL;
7255 }
7256
7257 if (squote) {
7258 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7259 err_code |= ERR_ALERT | ERR_FATAL;
7260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007261
7262 /* empty line */
7263 if (!**args)
7264 continue;
7265
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007266 if (*line) {
7267 /* we had to stop due to too many args.
7268 * Let's terminate the string, print the offending part then cut the
7269 * last arg.
7270 */
7271 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7272 line++;
7273 *line = '\0';
7274
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007275 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007276 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007277 err_code |= ERR_ALERT | ERR_FATAL;
7278 args[arg] = line;
7279 }
7280
Willy Tarreau540abe42007-05-02 20:50:16 +02007281 /* zero out remaining args and ensure that at least one entry
7282 * is zeroed out.
7283 */
7284 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007285 args[arg] = line;
7286 }
7287
Willy Tarreau3842f002009-06-14 11:39:52 +02007288 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007289 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007290 char *tmp;
7291
Willy Tarreau3842f002009-06-14 11:39:52 +02007292 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007293 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007294 for (arg=0; *args[arg+1]; arg++)
7295 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007296 *tmp = '\0'; // fix the next arg to \0
7297 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007298 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007299 else if (!strcmp(args[0], "default")) {
7300 kwm = KWM_DEF;
7301 for (arg=0; *args[arg+1]; arg++)
7302 args[arg] = args[arg+1]; // shift args after inversion
7303 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007304
William Lallemand0f99e342011-10-12 17:50:54 +02007305 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7306 strcmp(args[0], "log") != 0) {
7307 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007308 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007309 }
7310
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007311 /* detect section start */
7312 list_for_each_entry(ics, &sections, list) {
7313 if (strcmp(args[0], ics->section_name) == 0) {
7314 cursection = ics->section_name;
7315 cs = ics;
7316 break;
7317 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007318 }
7319
William Lallemandd2ff56d2017-10-16 11:06:50 +02007320 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007321 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007322 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007323 } else {
7324 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007325
William Lallemandd2ff56d2017-10-16 11:06:50 +02007326 if (pcs != cs && pcs && pcs->post_section_parser) {
7327 err_code |= pcs->post_section_parser();
7328 if (err_code & ERR_ABORT)
7329 goto err;
7330 }
7331
7332 err_code |= cs->section_parser(file, linenum, args, kwm);
7333 if (err_code & ERR_ABORT)
7334 goto err;
7335 }
7336 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007337 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007338
7339 if (pcs == cs && pcs && pcs->post_section_parser)
7340 err_code |= pcs->post_section_parser();
7341
7342err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007343 free(cfg_scope);
7344 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007345 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007346 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007347 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007348 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007349}
7350
Willy Tarreau64ab6072014-09-16 12:17:36 +02007351/* This function propagates processes from frontend <from> to backend <to> so
7352 * that it is always guaranteed that a backend pointed to by a frontend is
7353 * bound to all of its processes. After that, if the target is a "listen"
7354 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007355 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007356 * checked first to ensure that <to> is already bound to all processes of
7357 * <from>, there is no risk of looping and we ensure to follow the shortest
7358 * path to the destination.
7359 *
7360 * It is possible to set <to> to NULL for the first call so that the function
7361 * takes care of visiting the initial frontend in <from>.
7362 *
7363 * It is important to note that the function relies on the fact that all names
7364 * have already been resolved.
7365 */
7366void propagate_processes(struct proxy *from, struct proxy *to)
7367{
7368 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007369
7370 if (to) {
7371 /* check whether we need to go down */
7372 if (from->bind_proc &&
7373 (from->bind_proc & to->bind_proc) == from->bind_proc)
7374 return;
7375
7376 if (!from->bind_proc && !to->bind_proc)
7377 return;
7378
7379 to->bind_proc = from->bind_proc ?
7380 (to->bind_proc | from->bind_proc) : 0;
7381
7382 /* now propagate down */
7383 from = to;
7384 }
7385
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007386 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007387 return;
7388
Willy Tarreauf6b70012014-12-18 14:00:43 +01007389 if (from->state == PR_STSTOPPED)
7390 return;
7391
Willy Tarreau64ab6072014-09-16 12:17:36 +02007392 /* default_backend */
7393 if (from->defbe.be)
7394 propagate_processes(from, from->defbe.be);
7395
7396 /* use_backend */
7397 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007398 if (rule->dynamic)
7399 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007400 to = rule->be.backend;
7401 propagate_processes(from, to);
7402 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007403}
7404
Willy Tarreaubb925012009-07-23 13:36:36 +02007405/*
7406 * Returns the error code, 0 if OK, or any combination of :
7407 * - ERR_ABORT: must abort ASAP
7408 * - ERR_FATAL: we can continue parsing but not start the service
7409 * - ERR_WARN: a warning has been emitted
7410 * - ERR_ALERT: an alert has been emitted
7411 * Only the two first ones can stop processing, the two others are just
7412 * indicators.
7413 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007414int check_config_validity()
7415{
7416 int cfgerr = 0;
7417 struct proxy *curproxy = NULL;
7418 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007419 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007420 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007421 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007422 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007423 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007424
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007425 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007426 /*
7427 * Now, check for the integrity of all that we have collected.
7428 */
7429
7430 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007431 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007432
Willy Tarreau193b8c62012-11-22 00:17:38 +01007433 if (!global.tune.max_http_hdr)
7434 global.tune.max_http_hdr = MAX_HTTP_HDR;
7435
7436 if (!global.tune.cookie_len)
7437 global.tune.cookie_len = CAPTURE_LEN;
7438
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007439 if (!global.tune.requri_len)
7440 global.tune.requri_len = REQURI_LEN;
7441
Emeric Brun96fd9262017-07-05 13:33:16 +02007442 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7443
Willy Tarreau193b8c62012-11-22 00:17:38 +01007444 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7445
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007446 /* Post initialisation of the users and groups lists. */
7447 err_code = userlist_postinit();
7448 if (err_code != ERR_NONE)
7449 goto out;
7450
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007451 /* first, we will invert the proxy list order */
7452 curproxy = NULL;
7453 while (proxy) {
7454 struct proxy *next;
7455
7456 next = proxy->next;
7457 proxy->next = curproxy;
7458 curproxy = proxy;
7459 if (!next)
7460 break;
7461 proxy = next;
7462 }
7463
Willy Tarreau419ead82014-09-16 13:41:21 +02007464 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007465 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007466 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007467 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007468 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007469 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007470 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007471 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007472
Willy Tarreau050536d2012-10-04 08:47:34 +02007473 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007474 /* proxy ID not set, use automatic numbering with first
7475 * spare entry starting with next_pxid.
7476 */
7477 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7478 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7479 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007480 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007481 next_pxid++;
7482
Willy Tarreau55ea7572007-06-17 19:56:27 +02007483
Willy Tarreaubaaee002006-06-26 02:48:02 +02007484 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007485 /* ensure we don't keep listeners uselessly bound */
7486 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007487 free((void *)curproxy->table.peers.name);
7488 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007489 continue;
7490 }
7491
Willy Tarreau102df612014-05-07 23:56:38 +02007492 /* Check multi-process mode compatibility for the current proxy */
7493
7494 if (curproxy->bind_proc) {
7495 /* an explicit bind-process was specified, let's check how many
7496 * processes remain.
7497 */
David Carliere6c39412015-07-02 07:00:17 +00007498 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007499
7500 curproxy->bind_proc &= nbits(global.nbproc);
7501 if (!curproxy->bind_proc && nbproc == 1) {
7502 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);
7503 curproxy->bind_proc = 1;
7504 }
7505 else if (!curproxy->bind_proc && nbproc > 1) {
7506 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);
7507 curproxy->bind_proc = 0;
7508 }
7509 }
7510
Willy Tarreau3d209582014-05-09 17:06:11 +02007511 /* check and reduce the bind-proc of each listener */
7512 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7513 unsigned long mask;
7514
7515 if (!bind_conf->bind_proc)
7516 continue;
7517
7518 mask = nbits(global.nbproc);
7519 if (curproxy->bind_proc)
7520 mask &= curproxy->bind_proc;
7521 /* mask cannot be null here thanks to the previous checks */
7522
David Carliere6c39412015-07-02 07:00:17 +00007523 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007524 bind_conf->bind_proc &= mask;
7525
7526 if (!bind_conf->bind_proc && nbproc == 1) {
7527 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",
7528 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7529 bind_conf->bind_proc = mask & ~(mask - 1);
7530 }
7531 else if (!bind_conf->bind_proc && nbproc > 1) {
7532 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",
7533 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7534 bind_conf->bind_proc = 0;
7535 }
7536 }
7537
Willy Tarreauff01a212009-03-15 13:46:16 +01007538 switch (curproxy->mode) {
7539 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007540 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007541 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007542 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7543 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007544 cfgerr++;
7545 }
7546
7547 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007548 Warning("config : servers will be ignored for %s '%s'.\n",
7549 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007550 break;
7551
7552 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007553 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007554 break;
7555
7556 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007557 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007558 break;
7559 }
7560
Willy Tarreauf3934b82015-08-11 11:36:45 +02007561 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7562 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7563 proxy_type_str(curproxy), curproxy->id);
7564 err_code |= ERR_WARN;
7565 }
7566
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007567 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007568 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007569 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007570 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7571 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007572 cfgerr++;
7573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007574#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007575 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007576 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7577 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007578 cfgerr++;
7579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007580#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007581 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007582 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7583 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007584 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007585 }
7586 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007587 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007588 /* If no LB algo is set in a backend, and we're not in
7589 * transparent mode, dispatch mode nor proxy mode, we
7590 * want to use balance roundrobin by default.
7591 */
7592 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7593 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007594 }
7595 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007596
Willy Tarreau1620ec32011-08-06 17:05:02 +02007597 if (curproxy->options & PR_O_DISPATCH)
7598 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7599 else if (curproxy->options & PR_O_HTTP_PROXY)
7600 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7601 else if (curproxy->options & PR_O_TRANSP)
7602 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007603
Willy Tarreau1620ec32011-08-06 17:05:02 +02007604 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7605 if (curproxy->options & PR_O_DISABLE404) {
7606 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7607 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7608 err_code |= ERR_WARN;
7609 curproxy->options &= ~PR_O_DISABLE404;
7610 }
7611 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7612 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7613 "send-state", proxy_type_str(curproxy), curproxy->id);
7614 err_code |= ERR_WARN;
7615 curproxy->options &= ~PR_O2_CHK_SNDST;
7616 }
Willy Tarreauef781042010-01-27 11:53:01 +01007617 }
7618
Simon Horman98637e52014-06-20 12:30:16 +09007619 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7620 if (!global.external_check) {
7621 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7622 curproxy->id, "option external-check");
7623 cfgerr++;
7624 }
7625 if (!curproxy->check_command) {
7626 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7627 curproxy->id, "option external-check");
7628 cfgerr++;
7629 }
7630 }
7631
Simon Horman64e34162015-02-06 11:11:57 +09007632 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007633 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7634 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007635 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7636 "'email-alert myhostname', or 'email-alert to' "
7637 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007638 "to be present).\n",
7639 proxy_type_str(curproxy), curproxy->id);
7640 err_code |= ERR_WARN;
7641 free_email_alert(curproxy);
7642 }
7643 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007644 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007645 }
7646
Simon Horman98637e52014-06-20 12:30:16 +09007647 if (curproxy->check_command) {
7648 int clear = 0;
7649 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7650 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7651 "external-check command", proxy_type_str(curproxy), curproxy->id);
7652 err_code |= ERR_WARN;
7653 clear = 1;
7654 }
7655 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007656 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007657 curproxy->id, "external-check command");
7658 cfgerr++;
7659 }
7660 if (clear) {
7661 free(curproxy->check_command);
7662 curproxy->check_command = NULL;
7663 }
7664 }
7665
7666 if (curproxy->check_path) {
7667 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7668 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7669 "external-check path", proxy_type_str(curproxy), curproxy->id);
7670 err_code |= ERR_WARN;
7671 free(curproxy->check_path);
7672 curproxy->check_path = NULL;
7673 }
7674 }
7675
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007676 /* if a default backend was specified, let's find it */
7677 if (curproxy->defbe.name) {
7678 struct proxy *target;
7679
Willy Tarreauafb39922015-05-26 12:04:09 +02007680 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007681 if (!target) {
7682 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7683 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007684 cfgerr++;
7685 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007686 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7687 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007688 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007689 } else if (target->mode != curproxy->mode &&
7690 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7691
7692 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7693 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7694 curproxy->conf.file, curproxy->conf.line,
7695 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7696 target->conf.file, target->conf.line);
7697 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007698 } else {
7699 free(curproxy->defbe.name);
7700 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007701 /* Update tot_fe_maxconn for a further fullconn's computation */
7702 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007703 /* Emit a warning if this proxy also has some servers */
7704 if (curproxy->srv) {
7705 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7706 curproxy->id);
7707 err_code |= ERR_WARN;
7708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007709 }
7710 }
7711
Emeric Brun3f783572017-01-12 11:21:28 +01007712 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7713 /* Case of listen without default backend
7714 * The curproxy will be its own default backend
7715 * so we update tot_fe_maxconn for a further
7716 * fullconn's computation */
7717 curproxy->tot_fe_maxconn += curproxy->maxconn;
7718 }
7719
Willy Tarreau55ea7572007-06-17 19:56:27 +02007720 /* find the target proxy for 'use_backend' rules */
7721 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007722 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007723 struct logformat_node *node;
7724 char *pxname;
7725
7726 /* Try to parse the string as a log format expression. If the result
7727 * of the parsing is only one entry containing a simple string, then
7728 * it's a standard string corresponding to a static rule, thus the
7729 * parsing is cancelled and be.name is restored to be resolved.
7730 */
7731 pxname = rule->be.name;
7732 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007733 curproxy->conf.args.ctx = ARGC_UBK;
7734 curproxy->conf.args.file = rule->file;
7735 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007736 err = NULL;
7737 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7738 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7739 rule->file, rule->line, pxname, err);
7740 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007741 cfgerr++;
7742 continue;
7743 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007744 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7745
7746 if (!LIST_ISEMPTY(&rule->be.expr)) {
7747 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7748 rule->dynamic = 1;
7749 free(pxname);
7750 continue;
7751 }
7752 /* simple string: free the expression and fall back to static rule */
7753 free(node->arg);
7754 free(node);
7755 }
7756
7757 rule->dynamic = 0;
7758 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007759
Willy Tarreauafb39922015-05-26 12:04:09 +02007760 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007761 if (!target) {
7762 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7763 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007764 cfgerr++;
7765 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007766 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7767 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007768 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007769 } else if (target->mode != curproxy->mode &&
7770 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7771
7772 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7773 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7774 curproxy->conf.file, curproxy->conf.line,
7775 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7776 target->conf.file, target->conf.line);
7777 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007778 } else {
7779 free((void *)rule->be.name);
7780 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007781 /* For each target of switching rules, we update
7782 * their tot_fe_maxconn, except if a previous rule point
7783 * on the same backend or on the default backend */
7784 if (rule->be.backend != curproxy->defbe.be) {
7785 struct switching_rule *swrule;
7786
7787 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7788 if (rule == swrule) {
7789 target->tot_fe_maxconn += curproxy->maxconn;
7790 break;
7791 }
7792 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7793 /* there is multiple ref of this backend */
7794 break;
7795 }
7796 }
7797 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007798 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007799 }
7800
Willy Tarreau64ab6072014-09-16 12:17:36 +02007801 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007802 list_for_each_entry(srule, &curproxy->server_rules, list) {
7803 struct server *target = findserver(curproxy, srule->srv.name);
7804
7805 if (!target) {
7806 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7807 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7808 cfgerr++;
7809 continue;
7810 }
7811 free((void *)srule->srv.name);
7812 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007813 }
7814
Emeric Brunb982a3d2010-01-04 15:45:53 +01007815 /* find the target table for 'stick' rules */
7816 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7817 struct proxy *target;
7818
Emeric Brun1d33b292010-01-04 15:47:17 +01007819 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7820 if (mrule->flags & STK_IS_STORE)
7821 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7822
Emeric Brunb982a3d2010-01-04 15:45:53 +01007823 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007824 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007825 else
7826 target = curproxy;
7827
7828 if (!target) {
7829 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7830 curproxy->id, mrule->table.name);
7831 cfgerr++;
7832 }
7833 else if (target->table.size == 0) {
7834 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7835 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7836 cfgerr++;
7837 }
Willy Tarreau12785782012-04-27 21:37:17 +02007838 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7839 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007840 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7841 cfgerr++;
7842 }
7843 else {
7844 free((void *)mrule->table.name);
7845 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007846 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007847 }
7848 }
7849
7850 /* find the target table for 'store response' rules */
7851 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7852 struct proxy *target;
7853
Emeric Brun1d33b292010-01-04 15:47:17 +01007854 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7855
Emeric Brunb982a3d2010-01-04 15:45:53 +01007856 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007857 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007858 else
7859 target = curproxy;
7860
7861 if (!target) {
7862 Alert("Proxy '%s': unable to find store table '%s'.\n",
7863 curproxy->id, mrule->table.name);
7864 cfgerr++;
7865 }
7866 else if (target->table.size == 0) {
7867 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7868 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7869 cfgerr++;
7870 }
Willy Tarreau12785782012-04-27 21:37:17 +02007871 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7872 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007873 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7874 cfgerr++;
7875 }
7876 else {
7877 free((void *)mrule->table.name);
7878 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007879 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007880 }
7881 }
7882
Christopher Faulete4e830d2017-09-18 14:51:41 +02007883 /* check validity for 'tcp-request' layer 4 rules */
7884 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
7885 err = NULL;
7886 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7887 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7888 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01007889 cfgerr++;
7890 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007891 }
7892
Christopher Faulete4e830d2017-09-18 14:51:41 +02007893 /* check validity for 'tcp-request' layer 5 rules */
7894 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
7895 err = NULL;
7896 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7897 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7898 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007899 cfgerr++;
7900 }
7901 }
7902
Christopher Faulete4e830d2017-09-18 14:51:41 +02007903 /* check validity for 'tcp-request' layer 6 rules */
7904 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
7905 err = NULL;
7906 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7907 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7908 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007909 cfgerr++;
7910 }
7911 }
7912
Christopher Faulete4e830d2017-09-18 14:51:41 +02007913 /* check validity for 'http-request' layer 7 rules */
7914 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
7915 err = NULL;
7916 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7917 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7918 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007919 cfgerr++;
7920 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007921 }
7922
Christopher Faulete4e830d2017-09-18 14:51:41 +02007923 /* check validity for 'http-response' layer 7 rules */
7924 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
7925 err = NULL;
7926 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7927 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7928 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02007929 cfgerr++;
7930 }
Willy Tarreau09448f72014-06-25 18:12:15 +02007931 }
7932
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007933 /* move any "block" rules at the beginning of the http-request rules */
7934 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7935 /* insert block_rules into http_req_rules at the beginning */
7936 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7937 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7938 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7939 curproxy->http_req_rules.n = curproxy->block_rules.n;
7940 LIST_INIT(&curproxy->block_rules);
7941 }
7942
Emeric Brun32da3c42010-09-23 18:39:19 +02007943 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007944 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007945
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02007946 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02007947 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7948 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007949 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007950 break;
7951 }
7952 }
7953
7954 if (!curpeers) {
7955 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7956 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007957 free((void *)curproxy->table.peers.name);
7958 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007959 cfgerr++;
7960 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007961 else if (curpeers->state == PR_STSTOPPED) {
7962 /* silently disable this peers section */
7963 curproxy->table.peers.p = NULL;
7964 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007965 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007966 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7967 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007968 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007969 cfgerr++;
7970 }
7971 }
7972
Simon Horman9dc49962015-01-30 11:22:59 +09007973
7974 if (curproxy->email_alert.mailers.name) {
7975 struct mailers *curmailers = mailers;
7976
7977 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02007978 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09007979 break;
Simon Horman9dc49962015-01-30 11:22:59 +09007980 }
Simon Horman9dc49962015-01-30 11:22:59 +09007981 if (!curmailers) {
7982 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7983 curproxy->id, curproxy->email_alert.mailers.name);
7984 free_email_alert(curproxy);
7985 cfgerr++;
7986 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02007987 else {
7988 err = NULL;
7989 if (init_email_alert(curmailers, curproxy, &err)) {
7990 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7991 free(err);
7992 cfgerr++;
7993 }
7994 }
Simon Horman9dc49962015-01-30 11:22:59 +09007995 }
7996
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007997 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007998 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007999 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8000 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8001 "proxy", curproxy->id);
8002 cfgerr++;
8003 goto out_uri_auth_compat;
8004 }
8005
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008006 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008007 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008008 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008009 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008010
Willy Tarreau95fa4692010-02-01 13:05:50 +01008011 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8012 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008013
8014 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008015 uri_auth_compat_req[i++] = "realm";
8016 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8017 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008018
Willy Tarreau95fa4692010-02-01 13:05:50 +01008019 uri_auth_compat_req[i++] = "unless";
8020 uri_auth_compat_req[i++] = "{";
8021 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8022 uri_auth_compat_req[i++] = "}";
8023 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008024
Willy Tarreauff011f22011-01-06 17:51:27 +01008025 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8026 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008027 cfgerr++;
8028 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008029 }
8030
Willy Tarreauff011f22011-01-06 17:51:27 +01008031 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008032
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008033 if (curproxy->uri_auth->auth_realm) {
8034 free(curproxy->uri_auth->auth_realm);
8035 curproxy->uri_auth->auth_realm = NULL;
8036 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008037
8038 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008039 }
8040out_uri_auth_compat:
8041
Dragan Dosen43885c72015-10-01 13:18:13 +02008042 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008043 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008044 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8045 if (!curproxy->conf.logformat_sd_string) {
8046 /* set the default logformat_sd_string */
8047 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8048 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008049 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008050 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008051 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008052
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008053 /* compile the log format */
8054 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008055 if (curproxy->conf.logformat_string != default_http_log_format &&
8056 curproxy->conf.logformat_string != default_tcp_log_format &&
8057 curproxy->conf.logformat_string != clf_http_log_format)
8058 free(curproxy->conf.logformat_string);
8059 curproxy->conf.logformat_string = NULL;
8060 free(curproxy->conf.lfs_file);
8061 curproxy->conf.lfs_file = NULL;
8062 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008063
8064 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8065 free(curproxy->conf.logformat_sd_string);
8066 curproxy->conf.logformat_sd_string = NULL;
8067 free(curproxy->conf.lfsd_file);
8068 curproxy->conf.lfsd_file = NULL;
8069 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008070 }
8071
Willy Tarreau62a61232013-04-12 18:13:46 +02008072 if (curproxy->conf.logformat_string) {
8073 curproxy->conf.args.ctx = ARGC_LOG;
8074 curproxy->conf.args.file = curproxy->conf.lfs_file;
8075 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008076 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008077 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008078 SMP_VAL_FE_LOG_END, &err)) {
8079 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8080 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8081 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008082 cfgerr++;
8083 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008084 curproxy->conf.args.file = NULL;
8085 curproxy->conf.args.line = 0;
8086 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008087
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008088 if (curproxy->conf.logformat_sd_string) {
8089 curproxy->conf.args.ctx = ARGC_LOGSD;
8090 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8091 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008092 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008093 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 +01008094 SMP_VAL_FE_LOG_END, &err)) {
8095 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8096 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8097 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008098 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008099 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8100 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8101 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8102 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008103 cfgerr++;
8104 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008105 curproxy->conf.args.file = NULL;
8106 curproxy->conf.args.line = 0;
8107 }
8108
Willy Tarreau62a61232013-04-12 18:13:46 +02008109 if (curproxy->conf.uniqueid_format_string) {
8110 curproxy->conf.args.ctx = ARGC_UIF;
8111 curproxy->conf.args.file = curproxy->conf.uif_file;
8112 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008113 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008114 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 +01008115 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8116 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8117 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8118 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008119 cfgerr++;
8120 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008121 curproxy->conf.args.file = NULL;
8122 curproxy->conf.args.line = 0;
8123 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008124
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008125 /* only now we can check if some args remain unresolved.
8126 * This must be done after the users and groups resolution.
8127 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008128 cfgerr += smp_resolve_args(curproxy);
8129 if (!cfgerr)
8130 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008131
Willy Tarreau2738a142006-07-08 17:28:09 +02008132 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008133 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008134 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008135 (!curproxy->timeout.connect ||
8136 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008137 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008138 " | While not properly invalid, you will certainly encounter various problems\n"
8139 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008140 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008141 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008142 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008143 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008144
Willy Tarreau1fa31262007-12-03 00:36:16 +01008145 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8146 * We must still support older configurations, so let's find out whether those
8147 * parameters have been set or must be copied from contimeouts.
8148 */
8149 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008150 if (!curproxy->timeout.tarpit ||
8151 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008152 /* tarpit timeout not set. We search in the following order:
8153 * default.tarpit, curr.connect, default.connect.
8154 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008155 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008156 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008157 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008158 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008159 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008160 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008161 }
8162 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008163 (!curproxy->timeout.queue ||
8164 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008165 /* queue timeout not set. We search in the following order:
8166 * default.queue, curr.connect, default.connect.
8167 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008168 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008169 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008170 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008171 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008172 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008173 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008174 }
8175 }
8176
Willy Tarreau1620ec32011-08-06 17:05:02 +02008177 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008178 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008179 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008180 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008181 }
8182
Willy Tarreau215663d2014-06-13 18:30:23 +02008183 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8184 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8185 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8186 proxy_type_str(curproxy), curproxy->id);
8187 err_code |= ERR_WARN;
8188 }
8189
Willy Tarreau193b8c62012-11-22 00:17:38 +01008190 /* ensure that cookie capture length is not too large */
8191 if (curproxy->capture_len >= global.tune.cookie_len) {
8192 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8193 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8194 err_code |= ERR_WARN;
8195 curproxy->capture_len = global.tune.cookie_len - 1;
8196 }
8197
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008198 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008199 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008200 curproxy->req_cap_pool = create_pool("ptrcap",
8201 curproxy->nb_req_cap * sizeof(char *),
8202 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008203 }
8204
8205 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008206 curproxy->rsp_cap_pool = create_pool("ptrcap",
8207 curproxy->nb_rsp_cap * sizeof(char *),
8208 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008209 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008210
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008211 switch (curproxy->load_server_state_from_file) {
8212 case PR_SRV_STATE_FILE_UNSPEC:
8213 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8214 break;
8215 case PR_SRV_STATE_FILE_GLOBAL:
8216 if (!global.server_state_file) {
8217 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",
8218 curproxy->id);
8219 err_code |= ERR_WARN;
8220 }
8221 break;
8222 }
8223
Willy Tarreaubaaee002006-06-26 02:48:02 +02008224 /* first, we will invert the servers list order */
8225 newsrv = NULL;
8226 while (curproxy->srv) {
8227 struct server *next;
8228
8229 next = curproxy->srv->next;
8230 curproxy->srv->next = newsrv;
8231 newsrv = curproxy->srv;
8232 if (!next)
8233 break;
8234 curproxy->srv = next;
8235 }
8236
Willy Tarreau17edc812014-01-03 12:14:34 +01008237 /* Check that no server name conflicts. This causes trouble in the stats.
8238 * We only emit a warning for the first conflict affecting each server,
8239 * in order to avoid combinatory explosion if all servers have the same
8240 * name. We do that only for servers which do not have an explicit ID,
8241 * because these IDs were made also for distinguishing them and we don't
8242 * want to annoy people who correctly manage them.
8243 */
8244 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8245 struct server *other_srv;
8246
8247 if (newsrv->puid)
8248 continue;
8249
8250 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8251 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8252 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8253 newsrv->conf.file, newsrv->conf.line,
8254 proxy_type_str(curproxy), curproxy->id,
8255 newsrv->id, other_srv->conf.line);
8256 break;
8257 }
8258 }
8259 }
8260
Willy Tarreaudd701652010-05-25 23:03:02 +02008261 /* assign automatic UIDs to servers which don't have one yet */
8262 next_id = 1;
8263 newsrv = curproxy->srv;
8264 while (newsrv != NULL) {
8265 if (!newsrv->puid) {
8266 /* server ID not set, use automatic numbering with first
8267 * spare entry starting with next_svid.
8268 */
8269 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8270 newsrv->conf.id.key = newsrv->puid = next_id;
8271 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8272 }
8273 next_id++;
8274 newsrv = newsrv->next;
8275 }
8276
Willy Tarreau20697042007-11-15 23:26:18 +01008277 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008278 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008279
Willy Tarreau62c3be22012-01-20 13:12:32 +01008280 /*
8281 * If this server supports a maxconn parameter, it needs a dedicated
8282 * tasks to fill the emptied slots when a connection leaves.
8283 * Also, resolve deferred tracking dependency if needed.
8284 */
8285 newsrv = curproxy->srv;
8286 while (newsrv != NULL) {
8287 if (newsrv->minconn > newsrv->maxconn) {
8288 /* Only 'minconn' was specified, or it was higher than or equal
8289 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8290 * this will avoid further useless expensive computations.
8291 */
8292 newsrv->maxconn = newsrv->minconn;
8293 } else if (newsrv->maxconn && !newsrv->minconn) {
8294 /* minconn was not specified, so we set it to maxconn */
8295 newsrv->minconn = newsrv->maxconn;
8296 }
8297
Willy Tarreau17d45382016-12-22 21:16:08 +01008298 /* this will also properly set the transport layer for prod and checks */
8299 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8300 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8301 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8302 }
Emeric Brun94324a42012-10-11 14:00:19 +02008303
Willy Tarreau2f075e92013-12-03 11:11:34 +01008304 /* set the check type on the server */
8305 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8306
Willy Tarreau62c3be22012-01-20 13:12:32 +01008307 if (newsrv->trackit) {
8308 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008309 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008310 char *pname, *sname;
8311
8312 pname = newsrv->trackit;
8313 sname = strrchr(pname, '/');
8314
8315 if (sname)
8316 *sname++ = '\0';
8317 else {
8318 sname = pname;
8319 pname = NULL;
8320 }
8321
8322 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008323 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008324 if (!px) {
8325 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8326 proxy_type_str(curproxy), curproxy->id,
8327 newsrv->id, pname);
8328 cfgerr++;
8329 goto next_srv;
8330 }
8331 } else
8332 px = curproxy;
8333
8334 srv = findserver(px, sname);
8335 if (!srv) {
8336 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8337 proxy_type_str(curproxy), curproxy->id,
8338 newsrv->id, sname);
8339 cfgerr++;
8340 goto next_srv;
8341 }
8342
Willy Tarreau32091232014-05-16 13:52:00 +02008343 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8344 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8345 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008346 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008347 "tracking as it does not have any check nor agent enabled.\n",
8348 proxy_type_str(curproxy), curproxy->id,
8349 newsrv->id, px->id, srv->id);
8350 cfgerr++;
8351 goto next_srv;
8352 }
8353
8354 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8355
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008356 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008357 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8358 "belongs to a tracking chain looping back to %s/%s.\n",
8359 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008360 newsrv->id, px->id, srv->id, px->id,
8361 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008362 cfgerr++;
8363 goto next_srv;
8364 }
8365
8366 if (curproxy != px &&
8367 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8368 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8369 "tracking: disable-on-404 option inconsistency.\n",
8370 proxy_type_str(curproxy), curproxy->id,
8371 newsrv->id, px->id, srv->id);
8372 cfgerr++;
8373 goto next_srv;
8374 }
8375
Willy Tarreau62c3be22012-01-20 13:12:32 +01008376 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008377 newsrv->tracknext = srv->trackers;
8378 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008379
8380 free(newsrv->trackit);
8381 newsrv->trackit = NULL;
8382 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008383
Willy Tarreau62c3be22012-01-20 13:12:32 +01008384 next_srv:
8385 newsrv = newsrv->next;
8386 }
8387
Olivier Houchard4e694042017-03-14 20:01:29 +01008388 /*
8389 * Try to generate dynamic cookies for servers now.
8390 * It couldn't be done earlier, since at the time we parsed
8391 * the server line, we may not have known yet that we
8392 * should use dynamic cookies, or the secret key may not
8393 * have been provided yet.
8394 */
8395 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8396 newsrv = curproxy->srv;
8397 while (newsrv != NULL) {
8398 srv_set_dyncookie(newsrv);
8399 newsrv = newsrv->next;
8400 }
8401
8402 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008403 /* We have to initialize the server lookup mechanism depending
8404 * on what LB algorithm was choosen.
8405 */
8406
8407 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8408 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8409 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008410 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8411 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8412 init_server_map(curproxy);
8413 } else {
8414 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8415 fwrr_init_server_groups(curproxy);
8416 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008417 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008418
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008419 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008420 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8421 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8422 fwlc_init_server_tree(curproxy);
8423 } else {
8424 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8425 fas_init_server_tree(curproxy);
8426 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008427 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008428
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008429 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008430 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8431 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8432 chash_init_server_tree(curproxy);
8433 } else {
8434 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8435 init_server_map(curproxy);
8436 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008437 break;
8438 }
Christopher Faulet5b517552017-06-09 14:17:53 +02008439 SPIN_INIT(&curproxy->lbprm.lock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02008440
8441 if (curproxy->options & PR_O_LOGASAP)
8442 curproxy->to_log &= ~LW_BYTES;
8443
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008444 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008445 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8446 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008447 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8448 proxy_type_str(curproxy), curproxy->id);
8449 err_code |= ERR_WARN;
8450 }
8451
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008452 if (curproxy->mode != PR_MODE_HTTP) {
8453 int optnum;
8454
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008455 if (curproxy->uri_auth) {
8456 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8457 proxy_type_str(curproxy), curproxy->id);
8458 err_code |= ERR_WARN;
8459 curproxy->uri_auth = NULL;
8460 }
8461
Willy Tarreaude7dc882017-03-10 11:49:21 +01008462 if (curproxy->capture_name) {
8463 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8464 proxy_type_str(curproxy), curproxy->id);
8465 err_code |= ERR_WARN;
8466 }
8467
8468 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8469 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8470 proxy_type_str(curproxy), curproxy->id);
8471 err_code |= ERR_WARN;
8472 }
8473
8474 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8475 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8476 proxy_type_str(curproxy), curproxy->id);
8477 err_code |= ERR_WARN;
8478 }
8479
8480 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8481 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8482 proxy_type_str(curproxy), curproxy->id);
8483 err_code |= ERR_WARN;
8484 }
8485
8486 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8487 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8488 proxy_type_str(curproxy), curproxy->id);
8489 err_code |= ERR_WARN;
8490 }
8491
Willy Tarreau87cf5142011-08-19 22:57:24 +02008492 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008493 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8494 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8495 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008496 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008497 }
8498
8499 if (curproxy->options & PR_O_ORGTO) {
8500 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8501 "originalto", proxy_type_str(curproxy), curproxy->id);
8502 err_code |= ERR_WARN;
8503 curproxy->options &= ~PR_O_ORGTO;
8504 }
8505
8506 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8507 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8508 (curproxy->cap & cfg_opts[optnum].cap) &&
8509 (curproxy->options & cfg_opts[optnum].val)) {
8510 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8511 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8512 err_code |= ERR_WARN;
8513 curproxy->options &= ~cfg_opts[optnum].val;
8514 }
8515 }
8516
8517 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8518 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8519 (curproxy->cap & cfg_opts2[optnum].cap) &&
8520 (curproxy->options2 & cfg_opts2[optnum].val)) {
8521 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8522 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8523 err_code |= ERR_WARN;
8524 curproxy->options2 &= ~cfg_opts2[optnum].val;
8525 }
8526 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008527
Willy Tarreau29fbe512015-08-20 19:35:14 +02008528#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008529 if (curproxy->conn_src.bind_hdr_occ) {
8530 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008531 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008532 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008533 err_code |= ERR_WARN;
8534 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008535#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008536 }
8537
Willy Tarreaubaaee002006-06-26 02:48:02 +02008538 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008539 * ensure that we're not cross-dressing a TCP server into HTTP.
8540 */
8541 newsrv = curproxy->srv;
8542 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008543 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008544 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8545 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008546 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008547 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008548
Willy Tarreau0cec3312011-10-31 13:49:26 +01008549 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8550 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8551 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8552 err_code |= ERR_WARN;
8553 }
8554
Willy Tarreauc93cd162014-05-13 15:54:22 +02008555 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008556 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8557 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8558 err_code |= ERR_WARN;
8559 }
8560
Willy Tarreau29fbe512015-08-20 19:35:14 +02008561#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008562 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8563 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008564 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 +01008565 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008566 err_code |= ERR_WARN;
8567 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008568#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008569
8570 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8571 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8572 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8573 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8574 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8575 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",
8576 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8577 err_code |= ERR_WARN;
8578 }
8579
8580
8581 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8582 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",
8583 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8584 err_code |= ERR_WARN;
8585 }
8586 }
8587
Willy Tarreau21d2af32008-02-14 20:25:24 +01008588 newsrv = newsrv->next;
8589 }
8590
Willy Tarreaue42bd962014-09-16 16:21:19 +02008591 /* check if we have a frontend with "tcp-request content" looking at L7
8592 * with no inspect-delay
8593 */
8594 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008595 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8596 if (arule->action == ACT_TCP_CAPTURE &&
8597 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008598 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008599 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8600 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008601 break;
8602 }
8603
Christopher Faulete4e830d2017-09-18 14:51:41 +02008604 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008605 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8606 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8607 " This means that these rules will randomly find their contents. This can be fixed by"
8608 " setting the tcp-request inspect-delay.\n",
8609 proxy_type_str(curproxy), curproxy->id);
8610 err_code |= ERR_WARN;
8611 }
8612 }
8613
Christopher Fauletd7c91962015-04-30 11:48:27 +02008614 /* Check filter configuration, if any */
8615 cfgerr += flt_check(curproxy);
8616
Willy Tarreauc1a21672009-08-16 22:37:44 +02008617 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008618 if (!curproxy->accept)
8619 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008620
Willy Tarreauc1a21672009-08-16 22:37:44 +02008621 if (curproxy->tcp_req.inspect_delay ||
8622 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008623 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008624
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008625 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008626 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008627 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008628 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008629
8630 /* both TCP and HTTP must check switching rules */
8631 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008632
8633 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008634 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008635 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8636 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 +01008637 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008638 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8639 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008640 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008641 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008642 }
8643
8644 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008645 if (curproxy->tcp_req.inspect_delay ||
8646 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8647 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8648
Emeric Brun97679e72010-09-23 17:56:44 +02008649 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8650 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8651
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008652 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008653 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008654 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008655 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008656
8657 /* If the backend does requires RDP cookie persistence, we have to
8658 * enable the corresponding analyser.
8659 */
8660 if (curproxy->options2 & PR_O2_RDPC_PRST)
8661 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008662
8663 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008664 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008665 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8666 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 +01008667 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008668 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8669 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008670 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008671 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008672 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008673 }
8674
8675 /***********************************************************/
8676 /* At this point, target names have already been resolved. */
8677 /***********************************************************/
8678
8679 /* Check multi-process mode compatibility */
8680
8681 if (global.nbproc > 1 && global.stats_fe) {
8682 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8683 unsigned long mask;
8684
8685 mask = nbits(global.nbproc);
8686 if (global.stats_fe->bind_proc)
8687 mask &= global.stats_fe->bind_proc;
8688
8689 if (bind_conf->bind_proc)
8690 mask &= bind_conf->bind_proc;
8691
8692 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008693 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008694 break;
8695 }
8696 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8697 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");
8698 }
8699 }
8700
8701 /* Make each frontend inherit bind-process from its listeners when not specified. */
8702 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8703 if (curproxy->bind_proc)
8704 continue;
8705
8706 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8707 unsigned long mask;
8708
Willy Tarreaue428b082015-05-04 21:57:58 +02008709 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008710 curproxy->bind_proc |= mask;
8711 }
8712
8713 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008714 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008715 }
8716
8717 if (global.stats_fe) {
8718 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8719 unsigned long mask;
8720
Cyril Bonté06181952016-02-24 00:14:54 +01008721 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008722 global.stats_fe->bind_proc |= mask;
8723 }
8724 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008725 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008726 }
8727
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008728 /* propagate bindings from frontends to backends. Don't do it if there
8729 * are any fatal errors as we must not call it with unresolved proxies.
8730 */
8731 if (!cfgerr) {
8732 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8733 if (curproxy->cap & PR_CAP_FE)
8734 propagate_processes(curproxy, NULL);
8735 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008736 }
8737
8738 /* Bind each unbound backend to all processes when not specified. */
8739 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8740 if (curproxy->bind_proc)
8741 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008742 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008743 }
8744
8745 /*******************************************************/
8746 /* At this step, all proxies have a non-null bind_proc */
8747 /*******************************************************/
8748
8749 /* perform the final checks before creating tasks */
8750
8751 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8752 struct listener *listener;
8753 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008754
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008755 /* Configure SSL for each bind line.
8756 * Note: if configuration fails at some point, the ->ctx member
8757 * remains NULL so that listeners can later detach.
8758 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008759 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008760 if (bind_conf->xprt->prepare_bind_conf &&
8761 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008762 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008763 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008764
Willy Tarreaue6b98942007-10-29 01:09:36 +01008765 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008766 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008767 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008768 int nbproc;
8769
8770 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008771 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008772 nbits(global.nbproc));
8773
8774 if (!nbproc) /* no intersection between listener and frontend */
8775 nbproc = 1;
8776
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008777 if (!listener->luid) {
8778 /* listener ID not set, use automatic numbering with first
8779 * spare entry starting with next_luid.
8780 */
8781 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8782 listener->conf.id.key = listener->luid = next_id;
8783 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008784 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008785 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008786
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008787 /* enable separate counters */
8788 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008789 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008790 if (!listener->name)
8791 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008792 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008793
Willy Tarreaue6b98942007-10-29 01:09:36 +01008794 if (curproxy->options & PR_O_TCP_NOLING)
8795 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008796 if (!listener->maxconn)
8797 listener->maxconn = curproxy->maxconn;
8798 if (!listener->backlog)
8799 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008800 if (!listener->maxaccept)
8801 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8802
8803 /* we want to have an optimal behaviour on single process mode to
8804 * maximize the work at once, but in multi-process we want to keep
8805 * some fairness between processes, so we target half of the max
8806 * number of events to be balanced over all the processes the proxy
8807 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8808 * used to disable the limit.
8809 */
8810 if (listener->maxaccept > 0) {
8811 if (nbproc > 1)
8812 listener->maxaccept = (listener->maxaccept + 1) / 2;
8813 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8814 }
8815
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008816 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008817 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008818 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008819
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008820 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008821 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008822
Willy Tarreau620408f2016-10-21 16:37:51 +02008823 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8824 listener->options |= LI_O_TCP_L5_RULES;
8825
Willy Tarreaude3041d2010-05-31 10:56:17 +02008826 if (curproxy->mon_mask.s_addr)
8827 listener->options |= LI_O_CHK_MONNET;
8828
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008829 /* smart accept mode is automatic in HTTP mode */
8830 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008831 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008832 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8833 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008834 }
8835
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008836 /* Release unused SSL configs */
8837 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008838 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8839 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008840 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008841
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008842 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008843 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008844 int count, maxproc = 0;
8845
8846 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008847 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008848 if (count > maxproc)
8849 maxproc = count;
8850 }
8851 /* backends have 0, frontends have 1 or more */
8852 if (maxproc != 1)
8853 Warning("Proxy '%s': in multi-process mode, stats will be"
8854 " limited to process assigned to the current request.\n",
8855 curproxy->id);
8856
Willy Tarreau102df612014-05-07 23:56:38 +02008857 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8858 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8859 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008860 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008861 }
Willy Tarreau102df612014-05-07 23:56:38 +02008862 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8863 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8864 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008865 }
8866 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008867
8868 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02008869 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02008870 if (curproxy->task) {
8871 curproxy->task->context = curproxy;
8872 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02008873 } else {
8874 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8875 curproxy->id);
8876 cfgerr++;
8877 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008878 }
8879
Willy Tarreaufbb78422011-06-05 15:38:35 +02008880 /* automatically compute fullconn if not set. We must not do it in the
8881 * loop above because cross-references are not yet fully resolved.
8882 */
8883 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8884 /* If <fullconn> is not set, let's set it to 10% of the sum of
8885 * the possible incoming frontend's maxconns.
8886 */
8887 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008888 /* we have the sum of the maxconns in <total>. We only
8889 * keep 10% of that sum to set the default fullconn, with
8890 * a hard minimum of 1 (to avoid a divide by zero).
8891 */
Emeric Brun3f783572017-01-12 11:21:28 +01008892 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008893 if (!curproxy->fullconn)
8894 curproxy->fullconn = 1;
8895 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008896 }
8897
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008898 /*
8899 * Recount currently required checks.
8900 */
8901
8902 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8903 int optnum;
8904
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008905 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8906 if (curproxy->options & cfg_opts[optnum].val)
8907 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008908
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008909 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8910 if (curproxy->options2 & cfg_opts2[optnum].val)
8911 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008912 }
8913
Willy Tarreau0fca4832015-05-01 19:12:05 +02008914 /* compute the required process bindings for the peers */
8915 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8916 if (curproxy->table.peers.p)
8917 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8918
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008919 if (cfg_peers) {
8920 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02008921 struct peer *p, *pb;
8922
Willy Tarreau1e273012015-05-01 19:15:17 +02008923 /* Remove all peers sections which don't have a valid listener,
8924 * which are not used by any table, or which are bound to more
8925 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008926 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008927 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02008928 while (*last) {
8929 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008930
8931 if (curpeers->state == PR_STSTOPPED) {
8932 /* the "disabled" keyword was present */
8933 if (curpeers->peers_fe)
8934 stop_proxy(curpeers->peers_fe);
8935 curpeers->peers_fe = NULL;
8936 }
8937 else if (!curpeers->peers_fe) {
8938 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8939 curpeers->id, localpeer);
8940 }
David Carliere6c39412015-07-02 07:00:17 +00008941 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008942 /* either it's totally stopped or too much used */
8943 if (curpeers->peers_fe->bind_proc) {
8944 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008945 "running in different processes (%d different ones). "
8946 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008947 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008948 cfgerr++;
8949 }
8950 stop_proxy(curpeers->peers_fe);
8951 curpeers->peers_fe = NULL;
8952 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008953 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008954 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008955 last = &curpeers->next;
8956 continue;
8957 }
8958
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008959 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008960 p = curpeers->remote;
8961 while (p) {
8962 pb = p->next;
8963 free(p->id);
8964 free(p);
8965 p = pb;
8966 }
8967
8968 /* Destroy and unlink this curpeers section.
8969 * Note: curpeers is backed up into *last.
8970 */
8971 free(curpeers->id);
8972 curpeers = curpeers->next;
8973 free(*last);
8974 *last = curpeers;
8975 }
8976 }
8977
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008978 /* initialize stick-tables on backend capable proxies. This must not
8979 * be done earlier because the data size may be discovered while parsing
8980 * other proxies.
8981 */
8982 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8983 if (curproxy->state == PR_STSTOPPED)
8984 continue;
8985
8986 if (!stktable_init(&curproxy->table)) {
8987 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8988 cfgerr++;
8989 }
8990 }
8991
Simon Horman0d16a402015-01-30 11:22:58 +09008992 if (mailers) {
8993 struct mailers *curmailers = mailers, **last;
8994 struct mailer *m, *mb;
8995
8996 /* Remove all mailers sections which don't have a valid listener.
8997 * This can happen when a mailers section is never referenced.
8998 */
8999 last = &mailers;
9000 while (*last) {
9001 curmailers = *last;
9002 if (curmailers->users) {
9003 last = &curmailers->next;
9004 continue;
9005 }
9006
9007 Warning("Removing incomplete section 'mailers %s'.\n",
9008 curmailers->id);
9009
9010 m = curmailers->mailer_list;
9011 while (m) {
9012 mb = m->next;
9013 free(m->id);
9014 free(m);
9015 m = mb;
9016 }
9017
9018 /* Destroy and unlink this curmailers section.
9019 * Note: curmailers is backed up into *last.
9020 */
9021 free(curmailers->id);
9022 curmailers = curmailers->next;
9023 free(*last);
9024 *last = curmailers;
9025 }
9026 }
9027
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009028 /* Update server_state_file_name to backend name if backend is supposed to use
9029 * a server-state file locally defined and none has been provided */
9030 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9031 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9032 curproxy->server_state_file_name == NULL)
9033 curproxy->server_state_file_name = strdup(curproxy->id);
9034 }
9035
Willy Tarreau34eb6712011-10-24 18:15:04 +02009036 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009037 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009038 MEM_F_SHARED);
9039
William Lallemand48b4bb42017-10-23 14:36:34 +02009040 list_for_each_entry(postparser, &postparsers, list) {
9041 if (postparser->func)
9042 cfgerr += postparser->func();
9043 }
9044
Willy Tarreaubb925012009-07-23 13:36:36 +02009045 if (cfgerr > 0)
9046 err_code |= ERR_ALERT | ERR_FATAL;
9047 out:
9048 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009049}
9050
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009051/*
9052 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9053 * parsing sessions.
9054 */
9055void cfg_register_keywords(struct cfg_kw_list *kwl)
9056{
9057 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9058}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009059
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009060/*
9061 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9062 */
9063void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9064{
9065 LIST_DEL(&kwl->list);
9066 LIST_INIT(&kwl->list);
9067}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009068
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009069/* this function register new section in the haproxy configuration file.
9070 * <section_name> is the name of this new section and <section_parser>
9071 * is the called parser. If two section declaration have the same name,
9072 * only the first declared is used.
9073 */
9074int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009075 int (*section_parser)(const char *, int, char **, int),
9076 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009077{
9078 struct cfg_section *cs;
9079
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009080 list_for_each_entry(cs, &sections, list) {
9081 if (strcmp(cs->section_name, section_name) == 0) {
9082 Alert("register section '%s': already registered.\n", section_name);
9083 return 0;
9084 }
9085 }
9086
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009087 cs = calloc(1, sizeof(*cs));
9088 if (!cs) {
9089 Alert("register section '%s': out of memory.\n", section_name);
9090 return 0;
9091 }
9092
9093 cs->section_name = section_name;
9094 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009095 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009096
9097 LIST_ADDQ(&sections, &cs->list);
9098
9099 return 1;
9100}
9101
William Lallemand48b4bb42017-10-23 14:36:34 +02009102/* this function register a new function which will be called once the haproxy
9103 * configuration file has been parsed. It's useful to check dependencies
9104 * between sections or to resolve items once everything is parsed.
9105 */
9106int cfg_register_postparser(char *name, int (*func)())
9107{
9108 struct cfg_postparser *cp;
9109
9110 cp = calloc(1, sizeof(*cp));
9111 if (!cp) {
9112 Alert("register postparser '%s': out of memory.\n", name);
9113 return 0;
9114 }
9115 cp->name = name;
9116 cp->func = func;
9117
9118 LIST_ADDQ(&postparsers, &cp->list);
9119
9120 return 1;
9121}
9122
Willy Tarreaubaaee002006-06-26 02:48:02 +02009123/*
David Carlier845efb52015-09-25 11:49:18 +01009124 * free all config section entries
9125 */
9126void cfg_unregister_sections(void)
9127{
9128 struct cfg_section *cs, *ics;
9129
9130 list_for_each_entry_safe(cs, ics, &sections, list) {
9131 LIST_DEL(&cs->list);
9132 free(cs);
9133 }
9134}
9135
Christopher Faulet7110b402016-10-26 11:09:44 +02009136void cfg_backup_sections(struct list *backup_sections)
9137{
9138 struct cfg_section *cs, *ics;
9139
9140 list_for_each_entry_safe(cs, ics, &sections, list) {
9141 LIST_DEL(&cs->list);
9142 LIST_ADDQ(backup_sections, &cs->list);
9143 }
9144}
9145
9146void cfg_restore_sections(struct list *backup_sections)
9147{
9148 struct cfg_section *cs, *ics;
9149
9150 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9151 LIST_DEL(&cs->list);
9152 LIST_ADDQ(&sections, &cs->list);
9153 }
9154}
9155
Willy Tarreau659fbf02016-05-26 17:55:28 +02009156__attribute__((constructor))
9157static void cfgparse_init(void)
9158{
9159 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009160 cfg_register_section("listen", cfg_parse_listen, NULL);
9161 cfg_register_section("frontend", cfg_parse_listen, NULL);
9162 cfg_register_section("backend", cfg_parse_listen, NULL);
9163 cfg_register_section("defaults", cfg_parse_listen, NULL);
9164 cfg_register_section("global", cfg_parse_global, NULL);
9165 cfg_register_section("userlist", cfg_parse_users, NULL);
9166 cfg_register_section("peers", cfg_parse_peers, NULL);
9167 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9168 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9169 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009170}
9171
David Carlier845efb52015-09-25 11:49:18 +01009172/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009173 * Local variables:
9174 * c-indent-level: 8
9175 * c-basic-offset: 8
9176 * End:
9177 */