blob: 2245f51cf2f2936d0e41294b1f6d5431ef02c53b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Emeric Brunc60def82017-09-27 14:59:38 +020045#include <common/hathreads.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046
47#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020048#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020049#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010051#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020052#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090053#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020054#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010055#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056
Willy Tarreaueb0c6142007-05-07 00:53:22 +020057#include <proto/acl.h>
Christopher Faulet4fce0d82017-09-18 11:57:31 +020058#include <proto/action.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010059#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020061#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020063#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020064#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010065#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020066#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020067#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020068#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020069#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010070#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020071#include <proto/lb_fwlc.h>
72#include <proto/lb_fwrr.h>
73#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020075#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020076#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
William Lallemandd2ff56d2017-10-16 11:06:50 +0200131 int (*post_section_parser)();
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
William Lallemand48b4bb42017-10-23 14:36:34 +0200139/* store post configuration parsing */
140
141struct cfg_postparser {
142 struct list list;
143 char *name;
144 int (*func)();
145};
146
147struct list postparsers = LIST_HEAD_INIT(postparsers);
148
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100151 const char *name;
152 unsigned int val;
153 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100154 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100156};
157
158/* proxy->options */
159static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100160{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
162 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
163 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
165 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
166 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200168 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200169 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100170 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
172 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
173 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100175#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100179#endif
180
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100182};
183
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184/* proxy->options2 */
185static const struct cfg_opt cfg_opts2[] =
186{
187#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
189 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
190 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100191#else
192 { "splice-request", 0, 0, 0, 0 },
193 { "splice-response", 0, 0, 0, 0 },
194 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
197 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
198 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
199 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
200 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
201 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
202 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
203 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
204 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400205 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100206 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200207 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200208 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100209 { NULL, 0, 0, 0 }
210};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Willy Tarreau6daf3432008-01-22 16:44:08 +0100212static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
214int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100215int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100216char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200218/* List head of all known configuration keywords */
219static struct cfg_kw_list cfg_keywords = {
220 .list = LIST_HEAD_INIT(cfg_keywords.list)
221};
222
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223/*
224 * converts <str> to a list of listeners which are dynamically allocated.
225 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
226 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
227 * - <port> is a numerical port from 1 to 65535 ;
228 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
229 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200230 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
231 * not NULL, it must be a valid pointer to either NULL or a freeable area that
232 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200234int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235{
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 int port, end;
238
239 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200240
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 while (next && *next) {
William Lallemand75ea0a02017-11-15 19:02:58 +0100242 int inherited = 0;
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200243 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
246 str = next;
247 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100248 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249 *next++ = 0;
250 }
251
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100252 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200253 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200254 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100255 if (!ss2)
256 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100258 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100259 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200260 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100264 if (!port || !end) {
265 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
266 goto fail;
267 }
268
Emeric Bruned760922010-10-22 17:59:25 +0200269 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200270 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200271 goto fail;
272 }
273
274 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200275 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200276 goto fail;
277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100279 else if (ss2->ss_family == AF_UNSPEC) {
280 socklen_t addr_len;
William Lallemand75ea0a02017-11-15 19:02:58 +0100281 inherited = 1;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282
283 /* We want to attach to an already bound fd whose number
284 * is in the addr part of ss2 when cast to sockaddr_in.
285 * Note that by definition there is a single listener.
286 * We still have to determine the address family to
287 * register the correct protocol.
288 */
289 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
290 addr_len = sizeof(*ss2);
291 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
292 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
293 goto fail;
294 }
295
296 port = end = get_host_port(ss2);
297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100299 /* OK the address looks correct */
William Lallemand75ea0a02017-11-15 19:02:58 +0100300 if (!create_listeners(bind_conf, ss2, port, end, fd, inherited, err)) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200301 memprintf(err, "%s for address '%s'.\n", *err, str);
302 goto fail;
303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 } /* end while(next) */
305 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200306 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307 fail:
308 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310}
311
William Lallemand6e62fb62015-04-28 16:55:23 +0200312/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100313 * Report an error in <msg> when there are too many arguments. This version is
314 * intended to be used by keyword parsers so that the message will be included
315 * into the general error message. The index is the current keyword in args.
316 * Return 0 if the number of argument is correct, otherwise build a message and
317 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
318 * message may also be null, it will simply not be produced (useful to check only).
319 * <msg> and <err_code> are only affected on error.
320 */
321int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
322{
323 int i;
324
325 if (!*args[index + maxarg + 1])
326 return 0;
327
328 if (msg) {
329 *msg = NULL;
330 memprintf(msg, "%s", args[0]);
331 for (i = 1; i <= index; i++)
332 memprintf(msg, "%s %s", *msg, args[i]);
333
334 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
335 }
336 if (err_code)
337 *err_code |= ERR_ALERT | ERR_FATAL;
338
339 return 1;
340}
341
342/*
343 * same as too_many_args_idx with a 0 index
344 */
345int too_many_args(int maxarg, char **args, char **msg, int *err_code)
346{
347 return too_many_args_idx(maxarg, 0, args, msg, err_code);
348}
349
350/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200351 * Report a fatal Alert when there is too much arguments
352 * The index is the current keyword in args
353 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
354 * Fill err_code with an ERR_ALERT and an ERR_FATAL
355 */
356int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
357{
358 char *kw = NULL;
359 int i;
360
361 if (!*args[index + maxarg + 1])
362 return 0;
363
364 memprintf(&kw, "%s", args[0]);
365 for (i = 1; i <= index; i++) {
366 memprintf(&kw, "%s %s", kw, args[i]);
367 }
368
369 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
370 free(kw);
371 *err_code |= ERR_ALERT | ERR_FATAL;
372 return 1;
373}
374
375/*
376 * same as alertif_too_many_args_idx with a 0 index
377 */
378int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
379{
380 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
381}
382
Willy Tarreau620408f2016-10-21 16:37:51 +0200383/* Report a warning if a rule is placed after a 'tcp-request session' rule.
384 * Return 1 if the warning has been emitted, otherwise 0.
385 */
386int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
387{
388 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
389 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
390 file, line, arg);
391 return 1;
392 }
393 return 0;
394}
395
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200396/* Report a warning if a rule is placed after a 'tcp-request content' rule.
397 * Return 1 if the warning has been emitted, otherwise 0.
398 */
399int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
400{
401 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
402 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
403 file, line, arg);
404 return 1;
405 }
406 return 0;
407}
408
Willy Tarreau61d18892009-03-31 10:49:21 +0200409/* Report a warning if a rule is placed after a 'block' rule.
410 * Return 1 if the warning has been emitted, otherwise 0.
411 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200414 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
416 file, line, arg);
417 return 1;
418 }
419 return 0;
420}
421
Willy Tarreau5002f572014-04-23 01:32:02 +0200422/* Report a warning if a rule is placed after an 'http_request' rule.
423 * Return 1 if the warning has been emitted, otherwise 0.
424 */
425int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
426{
427 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
428 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
429 file, line, arg);
430 return 1;
431 }
432 return 0;
433}
434
Willy Tarreau61d18892009-03-31 10:49:21 +0200435/* Report a warning if a rule is placed after a reqrewrite rule.
436 * Return 1 if the warning has been emitted, otherwise 0.
437 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100438int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200439{
440 if (proxy->req_exp) {
441 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
442 file, line, arg);
443 return 1;
444 }
445 return 0;
446}
447
448/* Report a warning if a rule is placed after a reqadd rule.
449 * Return 1 if the warning has been emitted, otherwise 0.
450 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100453 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200454 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
455 file, line, arg);
456 return 1;
457 }
458 return 0;
459}
460
461/* Report a warning if a rule is placed after a redirect rule.
462 * Return 1 if the warning has been emitted, otherwise 0.
463 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100464int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200465{
466 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
467 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
468 file, line, arg);
469 return 1;
470 }
471 return 0;
472}
473
474/* Report a warning if a rule is placed after a 'use_backend' rule.
475 * Return 1 if the warning has been emitted, otherwise 0.
476 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100477int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200478{
479 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
480 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
481 file, line, arg);
482 return 1;
483 }
484 return 0;
485}
486
Willy Tarreauee445d92014-04-23 01:39:04 +0200487/* Report a warning if a rule is placed after a 'use-server' rule.
488 * Return 1 if the warning has been emitted, otherwise 0.
489 */
490int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
491{
492 if (!LIST_ISEMPTY(&proxy->server_rules)) {
493 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
494 file, line, arg);
495 return 1;
496 }
497 return 0;
498}
499
Willy Tarreaud39ad442016-11-25 15:16:12 +0100500/* report a warning if a redirect rule is dangerously placed */
501int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200502{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100503 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200504 warnif_rule_after_use_server(proxy, file, line, arg);
505}
506
Willy Tarreaud39ad442016-11-25 15:16:12 +0100507/* report a warning if a reqadd rule is dangerously placed */
508int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200509{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100510 return warnif_rule_after_redirect(proxy, file, line, arg) ||
511 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200512}
513
Willy Tarreaud39ad442016-11-25 15:16:12 +0100514/* report a warning if a reqxxx rule is dangerously placed */
515int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200516{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100517 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
518 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200519}
520
521/* report a warning if an http-request rule is dangerously placed */
522int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
523{
Willy Tarreau61d18892009-03-31 10:49:21 +0200524 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200526}
527
Willy Tarreaud39ad442016-11-25 15:16:12 +0100528/* report a warning if a block rule is dangerously placed */
529int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200530{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100531 return warnif_rule_after_http_req(proxy, file, line, arg) ||
532 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaud39ad442016-11-25 15:16:12 +0100535/* report a warning if a "tcp request content" rule is dangerously placed */
536int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200537{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100538 return warnif_rule_after_block(proxy, file, line, arg) ||
539 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200540}
541
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542/* report a warning if a "tcp request session" rule is dangerously placed */
543int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200544{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100545 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
546 warnif_misplaced_tcp_cont(proxy, file, line, arg);
547}
548
549/* report a warning if a "tcp request connection" rule is dangerously placed */
550int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
551{
552 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
553 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200554}
555
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556/* Report it if a request ACL condition uses some keywords that are incompatible
557 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
558 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
559 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100560 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100562{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100563 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567 return 0;
568
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100569 acl = acl_cond_conflicts(cond, where);
570 if (acl) {
571 if (acl->name && *acl->name)
572 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
573 file, line, acl->name, sample_ckp_names(where));
574 else
575 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200576 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100577 return ERR_WARN;
578 }
579 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100580 return 0;
581
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 if (acl->name && *acl->name)
583 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200584 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100585 else
586 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200587 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100588 return ERR_WARN;
589}
590
Christopher Faulet62519022017-10-16 15:49:32 +0200591/* Parse a string representing a process number or a set of processes. It must
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100592 * be "all", "odd", "even", a number between 1 and <LONGBITS> or a range with
Christopher Faulet5ab51772017-11-22 11:21:58 +0100593 * two such numbers delimited by a dash ('-'). On success, it returns
594 * 0. otherwise it returns 1 with an error message in <err>.
Christopher Faulet62519022017-10-16 15:49:32 +0200595 *
596 * Note: this function can also be used to parse a thread number or a set of
597 * threads.
598 */
Christopher Faulet5ab51772017-11-22 11:21:58 +0100599static int parse_process_number(const char *arg, unsigned long *proc, char **err)
Christopher Faulet62519022017-10-16 15:49:32 +0200600{
Christopher Faulet62519022017-10-16 15:49:32 +0200601 if (strcmp(arg, "all") == 0)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100602 *proc |= ~0UL;
Christopher Faulet62519022017-10-16 15:49:32 +0200603 else if (strcmp(arg, "odd") == 0)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100604 *proc |= ~0UL/3UL; /* 0x555....555 */
Christopher Faulet62519022017-10-16 15:49:32 +0200605 else if (strcmp(arg, "even") == 0)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100606 *proc |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Christopher Faulet62519022017-10-16 15:49:32 +0200607 else {
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100608 char *dash;
609 unsigned int low, high;
610
Christopher Faulet5ab51772017-11-22 11:21:58 +0100611 if (!isdigit((int)*arg)) {
612 memprintf(err, "'%s' is not a valid PROC number.\n", arg);
613 return -1;
614 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100615
616 low = high = str2uic(arg);
617 if ((dash = strchr(arg, '-')) != NULL)
618 high = str2uic(dash + 1);
619 if (high < low) {
620 unsigned int swap = low;
621 low = high;
622 high = swap;
623 }
624
Christopher Faulet5ab51772017-11-22 11:21:58 +0100625 if (low < 1 || low > LONGBITS || high > LONGBITS) {
626 memprintf(err, "'%s' is not a valid PROC number/range."
627 " It supports PROC numbers from 1 to %d.\n",
628 arg, LONGBITS);
629 return 1;
630 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100631
632 for (;low <= high; low++)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100633 *proc |= 1UL << (low-1);
Christopher Faulet62519022017-10-16 15:49:32 +0200634 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100635
636 end:
Christopher Faulet5ab51772017-11-22 11:21:58 +0100637 return 0;
Christopher Faulet62519022017-10-16 15:49:32 +0200638}
639
640/* Parse cpu sets. Each CPU set is either a unique number between 0 and
641 * <LONGBITS> or a range with two such numbers delimited by a dash
642 * ('-'). Multiple CPU numbers or ranges may be specified. On success, it
643 * returns 0. otherwise it returns 1 with an error message in <err>.
644 */
645static unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
646{
647 int cur_arg = 0;
648
649 *cpu_set = 0;
650 while (*args[cur_arg]) {
651 char *dash;
652 unsigned int low, high;
653
654 if (!isdigit((int)*args[cur_arg])) {
655 memprintf(err, "'%s' is not a CPU range.\n", args[cur_arg]);
656 return -1;
657 }
658
659 low = high = str2uic(args[cur_arg]);
660 if ((dash = strchr(args[cur_arg], '-')) != NULL)
661 high = str2uic(dash + 1);
662
663 if (high < low) {
664 unsigned int swap = low;
665 low = high;
666 high = swap;
667 }
668
669 if (high >= LONGBITS) {
670 memprintf(err, "supports CPU numbers from 0 to %d.\n", LONGBITS - 1);
671 return 1;
672 }
673
674 while (low <= high)
675 *cpu_set |= 1UL << low++;
676
677 cur_arg++;
678 }
679 return 0;
680}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 * parse a line in a <global> section. Returns the error code, 0 if OK, or
683 * any combination of :
684 * - ERR_ABORT: must abort ASAP
685 * - ERR_FATAL: we can continue parsing but not start the service
686 * - ERR_WARN: a warning has been emitted
687 * - ERR_ALERT: an alert has been emitted
688 * Only the two first ones can stop processing, the two others are just
689 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200691int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692{
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200694 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695
696 if (!strcmp(args[0], "global")) { /* new section */
697 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200698 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 }
701 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200702 if (alertif_too_many_args(0, file, linenum, args, &err_code))
703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704 global.mode |= MODE_DAEMON;
705 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200706 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200708 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200709 if (*args[1]) {
710 if (!strcmp(args[1], "exit-on-failure")) {
711 global.tune.options |= GTUNE_EXIT_ONFAILURE;
712 } else {
713 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200718 global.mode |= MODE_MWORKER;
719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200721 if (alertif_too_many_args(0, file, linenum, args, &err_code))
722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 global.mode |= MODE_DEBUG;
724 }
725 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200726 if (alertif_too_many_args(0, file, linenum, args, &err_code))
727 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100728 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200730 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200731 if (alertif_too_many_args(0, file, linenum, args, &err_code))
732 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100733 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200735 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200736 if (alertif_too_many_args(0, file, linenum, args, &err_code))
737 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100738 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100740 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200741 if (alertif_too_many_args(0, file, linenum, args, &err_code))
742 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100743 global.tune.options &= ~GTUNE_USE_SPLICE;
744 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200745 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200746 if (alertif_too_many_args(0, file, linenum, args, &err_code))
747 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200748 global.tune.options &= ~GTUNE_USE_GAI;
749 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000750 else if (!strcmp(args[0], "noreuseport")) {
751 if (alertif_too_many_args(0, file, linenum, args, &err_code))
752 goto out;
753 global.tune.options &= ~GTUNE_USE_REUSEPORT;
754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200755 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200756 if (alertif_too_many_args(0, file, linenum, args, &err_code))
757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 global.mode |= MODE_QUIET;
759 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200760 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200761 if (alertif_too_many_args(1, file, linenum, args, &err_code))
762 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200763 if (global.tune.maxpollevents != 0) {
764 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT;
766 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200767 }
768 if (*(args[1]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200772 }
773 global.tune.maxpollevents = atol(args[1]);
774 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100775 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
777 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100778 if (global.tune.maxaccept != 0) {
779 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT;
781 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100782 }
783 if (*(args[1]) == 0) {
784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100787 }
788 global.tune.maxaccept = atol(args[1]);
789 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200790 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200791 if (alertif_too_many_args(1, file, linenum, args, &err_code))
792 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798 global.tune.chksize = atol(args[1]);
799 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100800 else if (!strcmp(args[0], "tune.recv_enough")) {
801 if (alertif_too_many_args(1, file, linenum, args, &err_code))
802 goto out;
803 if (*(args[1]) == 0) {
804 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
807 }
808 global.tune.recv_enough = atol(args[1]);
809 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100810 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200811 if (alertif_too_many_args(1, file, linenum, args, &err_code))
812 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100813 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.buf_limit = atol(args[1]);
819 if (global.tune.buf_limit) {
820 if (global.tune.buf_limit < 3)
821 global.tune.buf_limit = 3;
822 if (global.tune.buf_limit <= global.tune.reserved_bufs)
823 global.tune.buf_limit = global.tune.reserved_bufs + 1;
824 }
825 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100826 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200827 if (alertif_too_many_args(1, file, linenum, args, &err_code))
828 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.reserved_bufs = atol(args[1]);
835 if (global.tune.reserved_bufs < 2)
836 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100837 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
838 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100839 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200840 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200841 if (alertif_too_many_args(1, file, linenum, args, &err_code))
842 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200843 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.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200849 if (global.tune.bufsize <= 0) {
850 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200854 }
855 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200856 if (alertif_too_many_args(1, file, linenum, args, &err_code))
857 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200858 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.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200864 if (global.tune.maxrewrite < 0) {
865 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200869 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100870 else if (!strcmp(args[0], "tune.idletimer")) {
871 unsigned int idle;
872 const char *res;
873
William Lallemand1a748ae2015-05-19 16:37:23 +0200874 if (alertif_too_many_args(1, file, linenum, args, &err_code))
875 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100876 if (*(args[1]) == 0) {
877 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881
882 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
883 if (res) {
884 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
885 file, linenum, *res, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889
890 if (idle > 65535) {
891 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
894 }
895 global.tune.idle_timer = idle;
896 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100897 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200898 if (alertif_too_many_args(1, file, linenum, args, &err_code))
899 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100900 if (global.tune.client_rcvbuf != 0) {
901 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
902 err_code |= ERR_ALERT;
903 goto out;
904 }
905 if (*(args[1]) == 0) {
906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910 global.tune.client_rcvbuf = atol(args[1]);
911 }
912 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200913 if (alertif_too_many_args(1, file, linenum, args, &err_code))
914 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100915 if (global.tune.server_rcvbuf != 0) {
916 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
917 err_code |= ERR_ALERT;
918 goto out;
919 }
920 if (*(args[1]) == 0) {
921 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
922 err_code |= ERR_ALERT | ERR_FATAL;
923 goto out;
924 }
925 global.tune.server_rcvbuf = atol(args[1]);
926 }
927 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200928 if (alertif_too_many_args(1, file, linenum, args, &err_code))
929 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100930 if (global.tune.client_sndbuf != 0) {
931 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
932 err_code |= ERR_ALERT;
933 goto out;
934 }
935 if (*(args[1]) == 0) {
936 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
937 err_code |= ERR_ALERT | ERR_FATAL;
938 goto out;
939 }
940 global.tune.client_sndbuf = atol(args[1]);
941 }
942 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200943 if (alertif_too_many_args(1, file, linenum, args, &err_code))
944 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100945 if (global.tune.server_sndbuf != 0) {
946 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT;
948 goto out;
949 }
950 if (*(args[1]) == 0) {
951 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955 global.tune.server_sndbuf = atol(args[1]);
956 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200957 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200958 if (alertif_too_many_args(1, file, linenum, args, &err_code))
959 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 global.tune.pipesize = atol(args[1]);
966 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100967 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200968 if (alertif_too_many_args(1, file, linenum, args, &err_code))
969 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100970 if (*(args[1]) == 0) {
971 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974 }
975 global.tune.cookie_len = atol(args[1]) + 1;
976 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200977 else if (!strcmp(args[0], "tune.http.logurilen")) {
978 if (alertif_too_many_args(1, file, linenum, args, &err_code))
979 goto out;
980 if (*(args[1]) == 0) {
981 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984 }
985 global.tune.requri_len = atol(args[1]) + 1;
986 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200987 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200988 if (alertif_too_many_args(1, file, linenum, args, &err_code))
989 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200990 if (*(args[1]) == 0) {
991 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200995 global.tune.max_http_hdr = atoi(args[1]);
996 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
997 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
998 file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001002 }
William Lallemandf3747832012-11-09 12:33:10 +01001003 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001004 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1005 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001006 if (*args[1]) {
1007 global.tune.comp_maxlevel = atoi(args[1]);
1008 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1009 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1010 file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 } else {
1015 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1016 file, linenum, args[0]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
1019 }
1020 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001021 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1022 if (*args[1]) {
1023 global.tune.pattern_cache = atoi(args[1]);
1024 if (global.tune.pattern_cache < 0) {
1025 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 } else {
1031 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1032 file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001038 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001041 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_ALERT;
1043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001044 }
1045 if (*(args[1]) == 0) {
1046 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001050 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1051 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]);
1052 err_code |= ERR_WARN;
1053 goto out;
1054 }
1055
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
1057 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001058 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001061 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001062 err_code |= ERR_ALERT;
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 }
1065 if (*(args[1]) == 0) {
1066 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001067 err_code |= ERR_ALERT | ERR_FATAL;
1068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001070 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1071 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]);
1072 err_code |= ERR_WARN;
1073 goto out;
1074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 }
Simon Horman98637e52014-06-20 12:30:16 +09001076 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001077 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1078 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001079 global.external_check = 1;
1080 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001081 /* user/group name handling */
1082 else if (!strcmp(args[0], "user")) {
1083 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001086 if (global.uid != 0) {
1087 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT;
1089 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001090 }
1091 errno = 0;
1092 ha_user = getpwnam(args[1]);
1093 if (ha_user != NULL) {
1094 global.uid = (int)ha_user->pw_uid;
1095 }
1096 else {
1097 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 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001099 }
1100 }
1101 else if (!strcmp(args[0], "group")) {
1102 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001105 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001106 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT;
1108 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 }
1110 errno = 0;
1111 ha_group = getgrnam(args[1]);
1112 if (ha_group != NULL) {
1113 global.gid = (int)ha_group->gr_gid;
1114 }
1115 else {
1116 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 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 }
1120 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001122 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001130 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1131 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1132 file, linenum, args[0], LONGBITS, global.nbproc);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
1135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
Christopher Fauletbe0faa22017-08-29 15:37:10 +02001137 else if (!strcmp(args[0], "nbthread")) {
1138 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1139 goto out;
1140 if (*(args[1]) == 0) {
1141 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
1144 }
1145 global.nbthread = atol(args[1]);
1146 if (global.nbthread < 1 || global.nbthread > LONGBITS) {
1147 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1148 file, linenum, args[0], LONGBITS, global.nbthread);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152#ifndef USE_THREAD
1153 if (global.nbthread > 1) {
1154 Alert("HAProxy is not compiled with threads support, please check build options for USE_THREAD.\n");
1155 global.nbthread = 1;
1156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
1158 }
1159#endif
1160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001162 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 if (global.maxconn != 0) {
1165 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT;
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 if (*(args[1]) == 0) {
1170 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 global.maxconn = atol(args[1]);
1175#ifdef SYSTEM_MAXCONN
1176 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1177 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);
1178 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001179 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 }
1181#endif /* SYSTEM_MAXCONN */
1182 }
Emeric Brun850efd52014-01-29 12:24:34 +01001183 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001184 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1185 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001186 if (*(args[1]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190 }
1191 if (strcmp(args[1],"none") == 0)
1192 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1193 else if (strcmp(args[1],"required") == 0)
1194 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1195 else {
1196 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001201 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001202 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1203 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001204 if (global.cps_lim != 0) {
1205 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1206 err_code |= ERR_ALERT;
1207 goto out;
1208 }
1209 if (*(args[1]) == 0) {
1210 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
1213 }
1214 global.cps_lim = atol(args[1]);
1215 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001216 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001217 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1218 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001219 if (global.sps_lim != 0) {
1220 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1221 err_code |= ERR_ALERT;
1222 goto out;
1223 }
1224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 global.sps_lim = atol(args[1]);
1230 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001231 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001232 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1233 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001234 if (global.ssl_lim != 0) {
1235 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1236 err_code |= ERR_ALERT;
1237 goto out;
1238 }
1239 if (*(args[1]) == 0) {
1240 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244 global.ssl_lim = atol(args[1]);
1245 }
William Lallemandd85f9172012-11-09 17:05:39 +01001246 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001247 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1248 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001249 if (*(args[1]) == 0) {
1250 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
1254 global.comp_rate_lim = atoi(args[1]) * 1024;
1255 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001256 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001257 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1258 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001259 if (global.maxpipes != 0) {
1260 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001261 err_code |= ERR_ALERT;
1262 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001263 }
1264 if (*(args[1]) == 0) {
1265 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001268 }
1269 global.maxpipes = atol(args[1]);
1270 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001271 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001274 if (*(args[1]) == 0) {
1275 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
William Lallemande3a7d992012-11-20 11:25:20 +01001279 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001280 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001281 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001282 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1283 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001284 if (*(args[1]) == 0) {
1285 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001290 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001291 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001295 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001296
Willy Tarreaubaaee002006-06-26 02:48:02 +02001297 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001298 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001300 if (global.rlimit_nofile != 0) {
1301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001302 err_code |= ERR_ALERT;
1303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 }
1305 if (*(args[1]) == 0) {
1306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001307 err_code |= ERR_ALERT | ERR_FATAL;
1308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 }
1310 global.rlimit_nofile = atol(args[1]);
1311 }
1312 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001313 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 if (global.chroot != NULL) {
1316 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001317 err_code |= ERR_ALERT;
1318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319 }
1320 if (*(args[1]) == 0) {
1321 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 }
1325 global.chroot = strdup(args[1]);
1326 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001327 else if (!strcmp(args[0], "description")) {
1328 int i, len=0;
1329 char *d;
1330
1331 if (!*args[1]) {
1332 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1333 file, linenum, args[0]);
1334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
1336 }
1337
Willy Tarreau348acfe2014-04-14 15:00:39 +02001338 for (i = 1; *args[i]; i++)
1339 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001340
1341 if (global.desc)
1342 free(global.desc);
1343
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001344 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001345
Willy Tarreau348acfe2014-04-14 15:00:39 +02001346 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1347 for (i = 2; *args[i]; i++)
1348 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001349 }
1350 else if (!strcmp(args[0], "node")) {
1351 int i;
1352 char c;
1353
William Lallemand1a748ae2015-05-19 16:37:23 +02001354 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1355 goto out;
1356
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001357 for (i=0; args[1][i]; i++) {
1358 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001359 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1360 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001361 break;
1362 }
1363
1364 if (!i || args[1][i]) {
1365 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1366 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1367 file, linenum, args[0]);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
1370 }
1371
1372 if (global.node)
1373 free(global.node);
1374
1375 global.node = strdup(args[1]);
1376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001378 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 if (global.pidfile != NULL) {
1381 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001382 err_code |= ERR_ALERT;
1383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
1385 if (*(args[1]) == 0) {
1386 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
1390 global.pidfile = strdup(args[1]);
1391 }
Emeric Bruned760922010-10-22 17:59:25 +02001392 else if (!strcmp(args[0], "unix-bind")) {
1393 int cur_arg = 1;
1394 while (*(args[cur_arg])) {
1395 if (!strcmp(args[cur_arg], "prefix")) {
1396 if (global.unix_bind.prefix != NULL) {
1397 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1398 err_code |= ERR_ALERT;
1399 cur_arg += 2;
1400 continue;
1401 }
1402
1403 if (*(args[cur_arg+1]) == 0) {
1404 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1405 err_code |= ERR_ALERT | ERR_FATAL;
1406 goto out;
1407 }
1408 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1409 cur_arg += 2;
1410 continue;
1411 }
1412
1413 if (!strcmp(args[cur_arg], "mode")) {
1414
1415 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1416 cur_arg += 2;
1417 continue;
1418 }
1419
1420 if (!strcmp(args[cur_arg], "uid")) {
1421
1422 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1423 cur_arg += 2;
1424 continue;
1425 }
1426
1427 if (!strcmp(args[cur_arg], "gid")) {
1428
1429 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1430 cur_arg += 2;
1431 continue;
1432 }
1433
1434 if (!strcmp(args[cur_arg], "user")) {
1435 struct passwd *user;
1436
1437 user = getpwnam(args[cur_arg + 1]);
1438 if (!user) {
1439 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1440 file, linenum, args[0], args[cur_arg + 1 ]);
1441 err_code |= ERR_ALERT | ERR_FATAL;
1442 goto out;
1443 }
1444
1445 global.unix_bind.ux.uid = user->pw_uid;
1446 cur_arg += 2;
1447 continue;
1448 }
1449
1450 if (!strcmp(args[cur_arg], "group")) {
1451 struct group *group;
1452
1453 group = getgrnam(args[cur_arg + 1]);
1454 if (!group) {
1455 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1456 file, linenum, args[0], args[cur_arg + 1 ]);
1457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
1459 }
1460
1461 global.unix_bind.ux.gid = group->gr_gid;
1462 cur_arg += 2;
1463 continue;
1464 }
1465
Willy Tarreaub48f9582011-09-05 01:17:06 +02001466 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001467 file, linenum, args[0]);
1468 err_code |= ERR_ALERT | ERR_FATAL;
1469 goto out;
1470 }
1471 }
William Lallemand0f99e342011-10-12 17:50:54 +02001472 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1473 /* delete previous herited or defined syslog servers */
1474 struct logsrv *back;
1475 struct logsrv *tmp;
1476
1477 if (*(args[1]) != 0) {
1478 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1479 err_code |= ERR_ALERT | ERR_FATAL;
1480 goto out;
1481 }
1482
1483 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1484 LIST_DEL(&tmp->list);
1485 free(tmp);
1486 }
1487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001489 struct sockaddr_storage *sk;
1490 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001491 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001492 int arg = 0;
1493 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001494
William Lallemand1a748ae2015-05-19 16:37:23 +02001495 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1496 goto out;
1497
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 if (*(args[1]) == 0 || *(args[2]) == 0) {
1499 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001500 err_code |= ERR_ALERT | ERR_FATAL;
1501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502 }
William Lallemand0f99e342011-10-12 17:50:54 +02001503
Vincent Bernat02779b62016-04-03 13:48:43 +02001504 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001505
Willy Tarreau18324f52014-06-27 18:10:07 +02001506 /* just after the address, a length may be specified */
1507 if (strcmp(args[arg+2], "len") == 0) {
1508 len = atoi(args[arg+3]);
1509 if (len < 80 || len > 65535) {
1510 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1511 file, linenum, args[arg+3]);
1512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto out;
1514 }
1515 logsrv->maxlen = len;
1516
1517 /* skip these two args */
1518 arg += 2;
1519 }
1520 else
1521 logsrv->maxlen = MAX_SYSLOG_LEN;
1522
Christopher Faulet084aa962017-08-29 16:54:41 +02001523 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001524 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001525
Dragan Dosen1322d092015-09-22 16:05:32 +02001526 /* after the length, a format may be specified */
1527 if (strcmp(args[arg+2], "format") == 0) {
1528 logsrv->format = get_log_format(args[arg+3]);
1529 if (logsrv->format < 0) {
1530 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001532 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001533 goto out;
1534 }
1535
1536 /* skip these two args */
1537 arg += 2;
1538 }
1539
David Carlier97880bb2016-04-08 10:35:26 +01001540 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1541 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001542 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001543 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001544
Willy Tarreau18324f52014-06-27 18:10:07 +02001545 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001546 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001547 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001548 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001549 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 }
1551
William Lallemand0f99e342011-10-12 17:50:54 +02001552 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001553 if (*(args[arg+3])) {
1554 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001555 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001556 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001557 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001558 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 }
1560 }
1561
William Lallemand0f99e342011-10-12 17:50:54 +02001562 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001563 if (*(args[arg+4])) {
1564 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001565 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001566 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001567 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001568 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001569 }
1570 }
1571
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001572 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001573 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001574 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001575 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001576 free(logsrv);
1577 goto out;
1578 }
1579 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001580
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001581 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001582 if (port1 != port2) {
1583 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1584 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001585 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001586 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001587 goto out;
1588 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001589
William Lallemand0f99e342011-10-12 17:50:54 +02001590 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001591 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001592 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001593 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594
William Lallemand0f99e342011-10-12 17:50:54 +02001595 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001596 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001597 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1598 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001599
1600 if (global.log_send_hostname != NULL) {
1601 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1602 err_code |= ERR_ALERT;
1603 goto out;
1604 }
1605
1606 if (*(args[1]))
1607 name = args[1];
1608 else
1609 name = hostname;
1610
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001611 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001612 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001613 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001614 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1615 if (global.server_state_base != NULL) {
1616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1617 err_code |= ERR_ALERT;
1618 goto out;
1619 }
1620
1621 if (!*(args[1])) {
1622 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1623 err_code |= ERR_FATAL;
1624 goto out;
1625 }
1626
1627 global.server_state_base = strdup(args[1]);
1628 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001629 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1630 if (global.server_state_file != NULL) {
1631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1632 err_code |= ERR_ALERT;
1633 goto out;
1634 }
1635
1636 if (!*(args[1])) {
1637 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1638 err_code |= ERR_FATAL;
1639 goto out;
1640 }
1641
1642 global.server_state_file = strdup(args[1]);
1643 }
Kevinm48936af2010-12-22 16:08:21 +00001644 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001645 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1646 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001647 if (*(args[1]) == 0) {
1648 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1649 err_code |= ERR_ALERT | ERR_FATAL;
1650 goto out;
1651 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001652 chunk_destroy(&global.log_tag);
1653 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001654 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001655 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001656 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1657 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001658 if (global.spread_checks != 0) {
1659 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001660 err_code |= ERR_ALERT;
1661 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001662 }
1663 if (*(args[1]) == 0) {
1664 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001667 }
1668 global.spread_checks = atol(args[1]);
1669 if (global.spread_checks < 0 || global.spread_checks > 50) {
1670 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001671 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001674 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1675 const char *err;
1676 unsigned int val;
1677
William Lallemand1a748ae2015-05-19 16:37:23 +02001678 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1679 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001680 if (*(args[1]) == 0) {
1681 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
1684 }
1685
1686 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1687 if (err) {
1688 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1689 err_code |= ERR_ALERT | ERR_FATAL;
1690 }
1691 global.max_spread_checks = val;
1692 if (global.max_spread_checks < 0) {
1693 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1694 err_code |= ERR_ALERT | ERR_FATAL;
1695 }
1696 }
Christopher Faulet62519022017-10-16 15:49:32 +02001697 else if (strcmp(args[0], "cpu-map") == 0) {
1698 /* map a process list to a CPU set */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001699#ifdef USE_CPU_AFFINITY
Christopher Faulet5ab51772017-11-22 11:21:58 +01001700 unsigned long proc = 0, cpus;
Christopher Faulet62519022017-10-16 15:49:32 +02001701 int i;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001702
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001703 if (!*args[1] || !*args[2]) {
1704 Alert("parsing [%s:%d] : %s expects a process number "
1705 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
Christopher Faulet62519022017-10-16 15:49:32 +02001706 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001707 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
1710 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001711
Christopher Faulet5ab51772017-11-22 11:21:58 +01001712 if (parse_process_number(args[1], &proc, &errmsg)) {
1713 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001714 err_code |= ERR_ALERT | ERR_FATAL;
1715 goto out;
1716 }
1717
Christopher Faulet62519022017-10-16 15:49:32 +02001718 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
1719 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001722 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001723 for (i = 0; i < LONGBITS; i++)
1724 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001725 global.cpu_map[i] = cpus;
1726#else
Christopher Faulet62519022017-10-16 15:49:32 +02001727 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1728 file, linenum, args[0]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Christopher Faulet62519022017-10-16 15:49:32 +02001731#endif /* ! USE_CPU_AFFINITY */
1732 }
1733 else if (strcmp(args[0], "thread-map") == 0) {
1734 /* map a thread list to a CPU set */
1735#ifdef USE_CPU_AFFINITY
1736#ifdef USE_THREAD
Christopher Faulet5ab51772017-11-22 11:21:58 +01001737 unsigned long proc = 0, thread = 0, cpus;
Christopher Faulet62519022017-10-16 15:49:32 +02001738 int i, j;
1739
Christopher Faulet5ab51772017-11-22 11:21:58 +01001740 if (!*args[1] || !*args[2] || !*args[3]) {
Christopher Faulet62519022017-10-16 15:49:32 +02001741 Alert("parsing [%s:%d]: %s expects a process number "
1742 "('all', 'odd', 'even', or a number from 1 to %d), "
1743 " followed by a thread number using the same format, "
1744 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
1745 file, linenum, args[0], LONGBITS, LONGBITS - 1);
1746 err_code |= ERR_ALERT | ERR_FATAL;
1747 goto out;
1748 }
Christopher Faulet5ab51772017-11-22 11:21:58 +01001749
1750 if (parse_process_number(args[1], &proc, &errmsg)) {
1751 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755 if (parse_process_number(args[2], &thread, &errmsg)) {
1756 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
Christopher Faulet62519022017-10-16 15:49:32 +02001760 if (parse_cpu_set((const char **)args+3, &cpus, &errmsg)) {
1761 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
1764 }
Christopher Faulet5ab51772017-11-22 11:21:58 +01001765
Christopher Faulet62519022017-10-16 15:49:32 +02001766 for (i = 0; i < LONGBITS; i++)
1767 if (proc & (1UL << i)) {
1768 for (j = 0; j < LONGBITS; j++)
1769 if (thread & (1UL << j))
1770 global.thread_map[i][j] = cpus;
1771 }
1772#else
1773 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_THREAD.\n",
1774 file, linenum, args[0]);
1775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
1777#endif /* ! USE_THREAD*/
1778#else
1779 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1780 file, linenum, args[0]);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783#endif /* ! USE_CPU_AFFINITY */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001784 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001785 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1786 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1787 goto out;
1788
1789 if (*(args[2]) == 0) {
1790 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
1793 }
1794
1795 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1796 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1797 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800 }
1801 }
1802 else if (!strcmp(args[0], "unsetenv")) {
1803 int arg;
1804
1805 if (*(args[1]) == 0) {
1806 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810
1811 for (arg = 1; *args[arg]; arg++) {
1812 if (unsetenv(args[arg]) != 0) {
1813 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817 }
1818 }
1819 else if (!strcmp(args[0], "resetenv")) {
1820 extern char **environ;
1821 char **env = environ;
1822
1823 /* args contain variable names to keep, one per argument */
1824 while (*env) {
1825 int arg;
1826
1827 /* look for current variable in among all those we want to keep */
1828 for (arg = 1; *args[arg]; arg++) {
1829 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1830 (*env)[strlen(args[arg])] == '=')
1831 break;
1832 }
1833
1834 /* delete this variable */
1835 if (!*args[arg]) {
1836 char *delim = strchr(*env, '=');
1837
1838 if (!delim || delim - *env >= trash.size) {
1839 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843
1844 memcpy(trash.str, *env, delim - *env);
1845 trash.str[delim - *env] = 0;
1846
1847 if (unsetenv(trash.str) != 0) {
1848 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
1851 }
1852 }
1853 else
1854 env++;
1855 }
1856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001858 struct cfg_kw_list *kwl;
1859 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001860 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001861
1862 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1863 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1864 if (kwl->kw[index].section != CFG_GLOBAL)
1865 continue;
1866 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001867 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001868 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001869 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001870 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001871 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001872 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001873 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001874 err_code |= ERR_WARN;
1875 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001876 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001877 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001878 }
1879 }
1880 }
1881
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001885
Willy Tarreau058e9072009-07-20 09:30:05 +02001886 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001887 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001888 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889}
1890
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001891void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001893 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 defproxy.mode = PR_MODE_TCP;
1895 defproxy.state = PR_STNEW;
1896 defproxy.maxconn = cfg_maxpconn;
1897 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001898 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001899 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001900
Simon Horman66183002013-02-23 10:16:43 +09001901 defproxy.defsrv.check.inter = DEF_CHKINTR;
1902 defproxy.defsrv.check.fastinter = 0;
1903 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001904 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1905 defproxy.defsrv.agent.fastinter = 0;
1906 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001907 defproxy.defsrv.check.rise = DEF_RISETIME;
1908 defproxy.defsrv.check.fall = DEF_FALLTIME;
1909 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1910 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001911 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001912 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001913 defproxy.defsrv.maxqueue = 0;
1914 defproxy.defsrv.minconn = 0;
1915 defproxy.defsrv.maxconn = 0;
1916 defproxy.defsrv.slowstart = 0;
1917 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1918 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1919 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001920
1921 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001922 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923}
1924
Willy Tarreauade5ec42010-01-28 19:33:49 +01001925
Willy Tarreau63af98d2014-05-18 08:11:41 +02001926/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1927 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1928 * ERR_FATAL in case of error.
1929 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001930static int create_cond_regex_rule(const char *file, int line,
1931 struct proxy *px, int dir, int action, int flags,
1932 const char *cmd, const char *reg, const char *repl,
1933 const char **cond_start)
1934{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001935 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001936 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001937 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001938 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001939 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001940 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001941 int cs;
1942 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001943
1944 if (px == &defproxy) {
1945 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001946 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001947 goto err;
1948 }
1949
1950 if (*reg == 0) {
1951 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001952 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001953 goto err;
1954 }
1955
Christopher Faulet898566e2016-10-26 11:06:28 +02001956 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001957 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001958
Willy Tarreau5321c422010-01-28 20:35:13 +01001959 if (cond_start &&
1960 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02001961 if ((cond = build_acl_cond(file, line, &px->acl, px, cond_start, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001962 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1963 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001964 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001965 goto err;
1966 }
1967 }
1968 else if (cond_start && **cond_start) {
1969 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1970 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001971 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001972 goto err;
1973 }
1974
Willy Tarreau63af98d2014-05-18 08:11:41 +02001975 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001976 (dir == SMP_OPT_DIR_REQ) ?
1977 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1978 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1979 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001980
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001981 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001982 if (!preg) {
1983 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001984 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001985 goto err;
1986 }
1987
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001988 cs = !(flags & REG_ICASE);
1989 cap = !(flags & REG_NOSUB);
1990 error = NULL;
1991 if (!regex_comp(reg, preg, cs, cap, &error)) {
1992 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1993 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001994 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001995 goto err;
1996 }
1997
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001998 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001999 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002000 if (repl && err) {
2001 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2002 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002003 ret_code |= ERR_ALERT | ERR_FATAL;
2004 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002005 }
2006
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002007 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002008 ret_code |= ERR_WARN;
2009
2010 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002011
Willy Tarreau63af98d2014-05-18 08:11:41 +02002012 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002013 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002014 err:
2015 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002016 free(errmsg);
2017 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002018}
2019
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020/*
William Lallemand51097192015-04-14 16:35:22 +02002021 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002022 * Returns the error code, 0 if OK, or any combination of :
2023 * - ERR_ABORT: must abort ASAP
2024 * - ERR_FATAL: we can continue parsing but not start the service
2025 * - ERR_WARN: a warning has been emitted
2026 * - ERR_ALERT: an alert has been emitted
2027 * Only the two first ones can stop processing, the two others are just
2028 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002030int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2031{
2032 static struct peers *curpeers = NULL;
2033 struct peer *newpeer = NULL;
2034 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002035 struct bind_conf *bind_conf;
2036 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002037 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002038 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002039
2040 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002041 if (!*args[1]) {
2042 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002043 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002044 goto out;
2045 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002046
William Lallemand6e62fb62015-04-28 16:55:23 +02002047 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2048 goto out;
2049
Emeric Brun32da3c42010-09-23 18:39:19 +02002050 err = invalid_char(args[1]);
2051 if (err) {
2052 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2053 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002054 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002055 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002056 }
2057
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002058 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002059 /*
2060 * If there are two proxies with the same name only following
2061 * combinations are allowed:
2062 */
2063 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002064 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 +02002065 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002066 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002067 }
2068 }
2069
Vincent Bernat02779b62016-04-03 13:48:43 +02002070 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2072 err_code |= ERR_ALERT | ERR_ABORT;
2073 goto out;
2074 }
2075
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002076 curpeers->next = cfg_peers;
2077 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002078 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002079 curpeers->conf.line = linenum;
2080 curpeers->last_change = now.tv_sec;
2081 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002082 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002083 }
2084 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002085 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002086 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002087 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002088
2089 if (!*args[2]) {
2090 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2091 file, linenum, args[0]);
2092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
2094 }
2095
2096 err = invalid_char(args[1]);
2097 if (err) {
2098 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2099 file, linenum, *err, args[1]);
2100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
2102 }
2103
Vincent Bernat02779b62016-04-03 13:48:43 +02002104 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002105 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2106 err_code |= ERR_ALERT | ERR_ABORT;
2107 goto out;
2108 }
2109
2110 /* the peers are linked backwards first */
2111 curpeers->count++;
2112 newpeer->next = curpeers->remote;
2113 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002114 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002115 newpeer->conf.line = linenum;
2116
2117 newpeer->last_change = now.tv_sec;
2118 newpeer->id = strdup(args[1]);
2119
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002120 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002121 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002122 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002123 err_code |= ERR_ALERT | ERR_FATAL;
2124 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002125 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002126
2127 proto = protocol_by_family(sk->ss_family);
2128 if (!proto || !proto->connect) {
2129 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2130 file, linenum, args[0], args[1]);
2131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
2133 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002134
2135 if (port1 != port2) {
2136 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2137 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002138 err_code |= ERR_ALERT | ERR_FATAL;
2139 goto out;
2140 }
2141
Willy Tarreau2aa38802013-02-20 19:20:59 +01002142 if (!port1) {
2143 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2144 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
2147 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002148
Emeric Brun32da3c42010-09-23 18:39:19 +02002149 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002150 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002151 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002152 newpeer->sock_init_arg = NULL;
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002153 HA_SPIN_INIT(&newpeer->lock);
Willy Tarreau26d8c592012-05-07 18:12:14 +02002154
Emeric Brun32da3c42010-09-23 18:39:19 +02002155 if (strcmp(newpeer->id, localpeer) == 0) {
2156 /* Current is local peer, it define a frontend */
2157 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002158 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002159
2160 if (!curpeers->peers_fe) {
2161 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2162 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2163 err_code |= ERR_ALERT | ERR_ABORT;
2164 goto out;
2165 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002166
Willy Tarreau237250c2011-07-29 01:49:03 +02002167 init_new_proxy(curpeers->peers_fe);
2168 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002169 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002170 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2171 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002172 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002173
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002174 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002175
Willy Tarreau902636f2013-03-10 19:44:48 +01002176 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2177 if (errmsg && *errmsg) {
2178 indent_msg(&errmsg, 2);
2179 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002180 }
2181 else
2182 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2183 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002184 err_code |= ERR_FATAL;
2185 goto out;
2186 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002187
2188 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002189 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002190 l->maxconn = curpeers->peers_fe->maxconn;
2191 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002192 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002193 l->analysers |= curpeers->peers_fe->fe_req_ana;
2194 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002195 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2196 global.maxsock += l->maxconn;
2197 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002198 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002199 else {
2200 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2201 file, linenum, args[0], args[1],
2202 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2203 err_code |= ERR_FATAL;
2204 goto out;
2205 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002206 }
2207 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002208 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2209 curpeers->state = PR_STSTOPPED;
2210 }
2211 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2212 curpeers->state = PR_STNEW;
2213 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002214 else if (*args[0] != 0) {
2215 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
2218 }
2219
2220out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002221 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002222 return err_code;
2223}
2224
Baptiste Assmann325137d2015-04-13 23:40:55 +02002225/*
2226 * Parse a <resolvers> section.
2227 * Returns the error code, 0 if OK, or any combination of :
2228 * - ERR_ABORT: must abort ASAP
2229 * - ERR_FATAL: we can continue parsing but not start the service
2230 * - ERR_WARN: a warning has been emitted
2231 * - ERR_ALERT: an alert has been emitted
2232 * Only the two first ones can stop processing, the two others are just
2233 * indicators.
2234 */
2235int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2236{
2237 static struct dns_resolvers *curr_resolvers = NULL;
2238 struct dns_nameserver *newnameserver = NULL;
2239 const char *err;
2240 int err_code = 0;
2241 char *errmsg = NULL;
2242
2243 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2244 if (!*args[1]) {
2245 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2246 err_code |= ERR_ALERT | ERR_ABORT;
2247 goto out;
2248 }
2249
2250 err = invalid_char(args[1]);
2251 if (err) {
2252 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2253 file, linenum, *err, args[0], args[1]);
2254 err_code |= ERR_ALERT | ERR_ABORT;
2255 goto out;
2256 }
2257
2258 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2259 /* Error if two resolvers owns the same name */
2260 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2261 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2262 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2263 err_code |= ERR_ALERT | ERR_ABORT;
2264 }
2265 }
2266
Vincent Bernat02779b62016-04-03 13:48:43 +02002267 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002268 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2269 err_code |= ERR_ALERT | ERR_ABORT;
2270 goto out;
2271 }
2272
2273 /* default values */
2274 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2275 curr_resolvers->conf.file = strdup(file);
2276 curr_resolvers->conf.line = linenum;
2277 curr_resolvers->id = strdup(args[1]);
2278 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002279 /* default maximum response size */
2280 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002281 /* default hold period for nx, other, refuse and timeout is 30s */
2282 curr_resolvers->hold.nx = 30000;
2283 curr_resolvers->hold.other = 30000;
2284 curr_resolvers->hold.refused = 30000;
2285 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002286 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002287 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002288 curr_resolvers->hold.valid = 10000;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002289 curr_resolvers->timeout.resolve = 1000;
2290 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002291 curr_resolvers->resolve_retries = 3;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002292 curr_resolvers->nb_nameservers = 0;
2293 LIST_INIT(&curr_resolvers->nameservers);
2294 LIST_INIT(&curr_resolvers->resolutions.curr);
2295 LIST_INIT(&curr_resolvers->resolutions.wait);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002296 HA_SPIN_INIT(&curr_resolvers->lock);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002297 }
2298 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2299 struct sockaddr_storage *sk;
2300 int port1, port2;
2301 struct protocol *proto;
2302
2303 if (!*args[2]) {
2304 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2305 file, linenum, args[0]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 err = invalid_char(args[1]);
2311 if (err) {
2312 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2313 file, linenum, *err, args[1]);
2314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
2316 }
2317
Christopher Faulet67957bd2017-09-27 11:00:59 +02002318 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002319 /* Error if two resolvers owns the same name */
2320 if (strcmp(newnameserver->id, args[1]) == 0) {
2321 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2322 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 }
2325 }
2326
Vincent Bernat02779b62016-04-03 13:48:43 +02002327 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002328 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2329 err_code |= ERR_ALERT | ERR_ABORT;
2330 goto out;
2331 }
2332
2333 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002334 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002335 newnameserver->resolvers = curr_resolvers;
2336 newnameserver->conf.file = strdup(file);
2337 newnameserver->conf.line = linenum;
2338 newnameserver->id = strdup(args[1]);
2339
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002340 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002341 if (!sk) {
2342 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346
2347 proto = protocol_by_family(sk->ss_family);
2348 if (!proto || !proto->connect) {
2349 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2350 file, linenum, args[0], args[1]);
2351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
2353 }
2354
2355 if (port1 != port2) {
2356 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2357 file, linenum, args[0], args[1], args[2]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002362 if (!port1 && !port2) {
2363 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2364 file, linenum, args[0], args[1]);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
2367 }
2368
Baptiste Assmann325137d2015-04-13 23:40:55 +02002369 newnameserver->addr = *sk;
2370 }
2371 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2372 const char *res;
2373 unsigned int time;
2374
2375 if (!*args[2]) {
2376 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2377 file, linenum, args[0]);
2378 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
2381 }
2382 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2383 if (res) {
2384 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2385 file, linenum, *res, args[0]);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002389 if (strcmp(args[1], "nx") == 0)
2390 curr_resolvers->hold.nx = time;
2391 else if (strcmp(args[1], "other") == 0)
2392 curr_resolvers->hold.other = time;
2393 else if (strcmp(args[1], "refused") == 0)
2394 curr_resolvers->hold.refused = time;
2395 else if (strcmp(args[1], "timeout") == 0)
2396 curr_resolvers->hold.timeout = time;
2397 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002398 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002399 else if (strcmp(args[1], "obsolete") == 0)
2400 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002401 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002402 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002403 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
2406 }
2407
2408 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002409 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002410 int i = 0;
2411
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002412 if (!*args[1]) {
2413 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2414 file, linenum, args[0]);
2415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
2417 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002418
2419 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002420 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2421 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2422 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002428 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002429 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002430 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2431 file, linenum, args[0]);
2432 err_code |= ERR_WARN;
2433 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002434 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002435 else if (strcmp(args[0], "resolve_retries") == 0) {
2436 if (!*args[1]) {
2437 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2438 file, linenum, args[0]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442 curr_resolvers->resolve_retries = atoi(args[1]);
2443 }
2444 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002445 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002446 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002447 file, linenum, args[0]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002451 else if (strcmp(args[1], "retry") == 0 ||
2452 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002453 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002454 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002455
2456 if (!*args[2]) {
2457 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2458 file, linenum, args[0], args[1]);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002462 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002463 if (res) {
2464 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2465 file, linenum, *res, args[0], args[1]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002469 if (args[1][2] == 't')
2470 curr_resolvers->timeout.retry = tout;
2471 else
2472 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002473 }
2474 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002475 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002476 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002480 } /* neither "nameserver" nor "resolvers" */
2481 else if (*args[0] != 0) {
2482 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487 out:
2488 free(errmsg);
2489 return err_code;
2490}
Simon Horman0d16a402015-01-30 11:22:58 +09002491
2492/*
William Lallemand51097192015-04-14 16:35:22 +02002493 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002494 * Returns the error code, 0 if OK, or any combination of :
2495 * - ERR_ABORT: must abort ASAP
2496 * - ERR_FATAL: we can continue parsing but not start the service
2497 * - ERR_WARN: a warning has been emitted
2498 * - ERR_ALERT: an alert has been emitted
2499 * Only the two first ones can stop processing, the two others are just
2500 * indicators.
2501 */
2502int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2503{
2504 static struct mailers *curmailers = NULL;
2505 struct mailer *newmailer = NULL;
2506 const char *err;
2507 int err_code = 0;
2508 char *errmsg = NULL;
2509
2510 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2511 if (!*args[1]) {
2512 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2513 err_code |= ERR_ALERT | ERR_ABORT;
2514 goto out;
2515 }
2516
2517 err = invalid_char(args[1]);
2518 if (err) {
2519 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2520 file, linenum, *err, args[0], args[1]);
2521 err_code |= ERR_ALERT | ERR_ABORT;
2522 goto out;
2523 }
2524
2525 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2526 /*
2527 * If there are two proxies with the same name only following
2528 * combinations are allowed:
2529 */
2530 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002531 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 +09002532 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002534 }
2535 }
2536
Vincent Bernat02779b62016-04-03 13:48:43 +02002537 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002538 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2539 err_code |= ERR_ALERT | ERR_ABORT;
2540 goto out;
2541 }
2542
2543 curmailers->next = mailers;
2544 mailers = curmailers;
2545 curmailers->conf.file = strdup(file);
2546 curmailers->conf.line = linenum;
2547 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002548 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2549 * But need enough time so that timeouts don't occur
2550 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002551 }
2552 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2553 struct sockaddr_storage *sk;
2554 int port1, port2;
2555 struct protocol *proto;
2556
2557 if (!*args[2]) {
2558 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2559 file, linenum, args[0]);
2560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
2562 }
2563
2564 err = invalid_char(args[1]);
2565 if (err) {
2566 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2567 file, linenum, *err, args[1]);
2568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
2570 }
2571
Vincent Bernat02779b62016-04-03 13:48:43 +02002572 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002573 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2574 err_code |= ERR_ALERT | ERR_ABORT;
2575 goto out;
2576 }
2577
2578 /* the mailers are linked backwards first */
2579 curmailers->count++;
2580 newmailer->next = curmailers->mailer_list;
2581 curmailers->mailer_list = newmailer;
2582 newmailer->mailers = curmailers;
2583 newmailer->conf.file = strdup(file);
2584 newmailer->conf.line = linenum;
2585
2586 newmailer->id = strdup(args[1]);
2587
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002588 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002589 if (!sk) {
2590 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
2593 }
2594
2595 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002596 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2597 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002598 file, linenum, args[0], args[1]);
2599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
2602
2603 if (port1 != port2) {
2604 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2605 file, linenum, args[0], args[1], args[2]);
2606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
2608 }
2609
2610 if (!port1) {
2611 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2612 file, linenum, args[0], args[1], args[2]);
2613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
2615 }
2616
2617 newmailer->addr = *sk;
2618 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002619 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002620 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002621 }
2622 else if (strcmp(args[0], "timeout") == 0) {
2623 if (!*args[1]) {
2624 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2625 file, linenum, args[0]);
2626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
2628 }
2629 else if (strcmp(args[1], "mail") == 0) {
2630 const char *res;
2631 unsigned int timeout_mail;
2632 if (!*args[2]) {
2633 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2634 file, linenum, args[0], args[1]);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637 }
2638 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2639 if (res) {
2640 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2641 file, linenum, *res, args[0]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645 if (timeout_mail <= 0) {
2646 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
2649 }
2650 curmailers->timeout.mail = timeout_mail;
2651 } else {
2652 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2653 file, linenum, args[0], args[1]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657 }
Simon Horman0d16a402015-01-30 11:22:58 +09002658 else if (*args[0] != 0) {
2659 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663
2664out:
2665 free(errmsg);
2666 return err_code;
2667}
2668
Simon Horman9dc49962015-01-30 11:22:59 +09002669static void free_email_alert(struct proxy *p)
2670{
2671 free(p->email_alert.mailers.name);
2672 p->email_alert.mailers.name = NULL;
2673 free(p->email_alert.from);
2674 p->email_alert.from = NULL;
2675 free(p->email_alert.to);
2676 p->email_alert.to = NULL;
2677 free(p->email_alert.myhostname);
2678 p->email_alert.myhostname = NULL;
2679}
2680
Willy Tarreau3842f002009-06-14 11:39:52 +02002681int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682{
2683 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002684 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002685 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002686 int rc;
2687 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002688 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002689 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002690 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002691 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002692 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693
Willy Tarreau977b8e42006-12-29 14:19:17 +01002694 if (!strcmp(args[0], "listen"))
2695 rc = PR_CAP_LISTEN;
2696 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002697 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002698 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002699 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002700 else
2701 rc = PR_CAP_NONE;
2702
2703 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 if (!*args[1]) {
2705 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002706 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_ABORT;
2709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002711
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002712 err = invalid_char(args[1]);
2713 if (err) {
2714 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2715 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002717 }
2718
Willy Tarreau8f50b682015-05-26 11:45:02 +02002719 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2720 if (curproxy) {
2721 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2722 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2723 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002724 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002725 }
2726
Vincent Bernat02779b62016-04-03 13:48:43 +02002727 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_ABORT;
2730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002732
Willy Tarreau97cb7802010-01-03 20:23:58 +01002733 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 curproxy->next = proxy;
2735 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002736 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2737 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002738 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002740 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002741 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742
William Lallemand6e62fb62015-04-28 16:55:23 +02002743 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2744 if (curproxy->cap & PR_CAP_FE)
2745 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 }
2748
2749 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002750 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002751 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002755 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002756 curproxy->no_options = defproxy.no_options;
2757 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002758 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002759 curproxy->except_net = defproxy.except_net;
2760 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002761 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002762 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002764 if (defproxy.fwdfor_hdr_len) {
2765 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2766 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2767 }
2768
Willy Tarreaub86db342009-11-30 11:50:16 +01002769 if (defproxy.orgto_hdr_len) {
2770 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2771 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2772 }
2773
Mark Lamourinec2247f02012-01-04 13:02:01 -05002774 if (defproxy.server_id_hdr_len) {
2775 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2776 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2777 }
2778
Willy Tarreau977b8e42006-12-29 14:19:17 +01002779 if (curproxy->cap & PR_CAP_FE) {
2780 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002781 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002782 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783
2784 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002785 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2786 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002787
2788 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790
Willy Tarreau977b8e42006-12-29 14:19:17 +01002791 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002792 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002793 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002794 curproxy->fullconn = defproxy.fullconn;
2795 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002796 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002797 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002799 if (defproxy.check_req) {
2800 curproxy->check_req = calloc(1, defproxy.check_len);
2801 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2802 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002803 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002805 if (defproxy.expect_str) {
2806 curproxy->expect_str = strdup(defproxy.expect_str);
2807 if (defproxy.expect_regex) {
2808 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002809 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2810 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002811 }
2812 }
2813
Willy Tarreau67402132012-05-31 20:40:20 +02002814 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002815 if (defproxy.cookie_name)
2816 curproxy->cookie_name = strdup(defproxy.cookie_name);
2817 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002818
2819 if (defproxy.dyncookie_key)
2820 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002821 if (defproxy.cookie_domain)
2822 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002823
Willy Tarreau31936852010-10-06 16:59:56 +02002824 if (defproxy.cookie_maxidle)
2825 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2826
2827 if (defproxy.cookie_maxlife)
2828 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2829
Emeric Brun647caf12009-06-30 17:57:00 +02002830 if (defproxy.rdp_cookie_name)
2831 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2832 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2833
Willy Tarreau01732802007-11-01 22:48:15 +01002834 if (defproxy.url_param_name)
2835 curproxy->url_param_name = strdup(defproxy.url_param_name);
2836 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002837
Benoitaffb4812009-03-25 13:02:10 +01002838 if (defproxy.hh_name)
2839 curproxy->hh_name = strdup(defproxy.hh_name);
2840 curproxy->hh_len = defproxy.hh_len;
2841 curproxy->hh_match_domain = defproxy.hh_match_domain;
2842
Willy Tarreauef9a3602012-12-08 22:29:20 +01002843 if (defproxy.conn_src.iface_name)
2844 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2845 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002846 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002847#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002848 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002849#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002850 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002853 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854 if (defproxy.capture_name)
2855 curproxy->capture_name = strdup(defproxy.capture_name);
2856 curproxy->capture_namelen = defproxy.capture_namelen;
2857 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859
Willy Tarreau977b8e42006-12-29 14:19:17 +01002860 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002861 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002862 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002863 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002864 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002865 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002866 curproxy->mon_net = defproxy.mon_net;
2867 curproxy->mon_mask = defproxy.mon_mask;
2868 if (defproxy.monitor_uri)
2869 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2870 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002871 if (defproxy.defbe.name)
2872 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002873
2874 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002875 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2876 if (curproxy->conf.logformat_string &&
2877 curproxy->conf.logformat_string != default_http_log_format &&
2878 curproxy->conf.logformat_string != default_tcp_log_format &&
2879 curproxy->conf.logformat_string != clf_http_log_format)
2880 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2881
2882 if (defproxy.conf.lfs_file) {
2883 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2884 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2885 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002886
2887 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2888 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2889 if (curproxy->conf.logformat_sd_string &&
2890 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2891 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2892
2893 if (defproxy.conf.lfsd_file) {
2894 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2895 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2896 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 }
2898
2899 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002900 curproxy->timeout.connect = defproxy.timeout.connect;
2901 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002902 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002903 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002904 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002905 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002906 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002907 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002908 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002909 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002910 }
2911
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002913 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002914
2915 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002916 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002917 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002918 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002919 LIST_INIT(&node->list);
2920 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2921 }
2922
Willy Tarreau62a61232013-04-12 18:13:46 +02002923 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2924 if (curproxy->conf.uniqueid_format_string)
2925 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2926
Dragan Dosen43885c72015-10-01 13:18:13 +02002927 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002928
Willy Tarreau62a61232013-04-12 18:13:46 +02002929 if (defproxy.conf.uif_file) {
2930 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2931 curproxy->conf.uif_line = defproxy.conf.uif_line;
2932 }
William Lallemanda73203e2012-03-12 12:48:57 +01002933
2934 /* copy default header unique id */
2935 if (defproxy.header_unique_id)
2936 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2937
William Lallemand82fe75c2012-10-23 10:25:10 +02002938 /* default compression options */
2939 if (defproxy.comp != NULL) {
2940 curproxy->comp = calloc(1, sizeof(struct comp));
2941 curproxy->comp->algos = defproxy.comp->algos;
2942 curproxy->comp->types = defproxy.comp->types;
2943 }
2944
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002946 curproxy->conf.used_listener_id = EB_ROOT;
2947 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002948
Simon Horman98637e52014-06-20 12:30:16 +09002949 if (defproxy.check_path)
2950 curproxy->check_path = strdup(defproxy.check_path);
2951 if (defproxy.check_command)
2952 curproxy->check_command = strdup(defproxy.check_command);
2953
Simon Horman9dc49962015-01-30 11:22:59 +09002954 if (defproxy.email_alert.mailers.name)
2955 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2956 if (defproxy.email_alert.from)
2957 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2958 if (defproxy.email_alert.to)
2959 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2960 if (defproxy.email_alert.myhostname)
2961 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002962 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002963 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002964
Willy Tarreau93893792009-07-23 13:19:11 +02002965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2968 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002969 /* FIXME-20070101: we should do this too at the end of the
2970 * config parsing to free all default values.
2971 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002972 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2973 err_code |= ERR_ABORT;
2974 goto out;
2975 }
2976
Willy Tarreaua534fea2008-08-03 12:19:50 +02002977 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002978 free(defproxy.check_command);
2979 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002980 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002981 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002982 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002983 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002984 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002985 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002986 free(defproxy.capture_name);
2987 free(defproxy.monitor_uri);
2988 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002989 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002990 free(defproxy.fwdfor_hdr_name);
2991 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002992 free(defproxy.orgto_hdr_name);
2993 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002994 free(defproxy.server_id_hdr_name);
2995 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002996 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002997 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002998 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002999 free(defproxy.expect_regex);
3000 defproxy.expect_regex = NULL;
3001 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003002
Willy Tarreau62a61232013-04-12 18:13:46 +02003003 if (defproxy.conf.logformat_string != default_http_log_format &&
3004 defproxy.conf.logformat_string != default_tcp_log_format &&
3005 defproxy.conf.logformat_string != clf_http_log_format)
3006 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003007
Willy Tarreau62a61232013-04-12 18:13:46 +02003008 free(defproxy.conf.uniqueid_format_string);
3009 free(defproxy.conf.lfs_file);
3010 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003011 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003012 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003013
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003014 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3015 free(defproxy.conf.logformat_sd_string);
3016 free(defproxy.conf.lfsd_file);
3017
Willy Tarreaua534fea2008-08-03 12:19:50 +02003018 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003019 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003020
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 /* we cannot free uri_auth because it might already be used */
3022 init_default_instance();
3023 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003024 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3025 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003026 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 }
3029 else if (curproxy == NULL) {
3030 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003034
3035 /* update the current file and line being parsed */
3036 curproxy->conf.args.file = curproxy->conf.file;
3037 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003038
3039 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02003040 if (!strcmp(args[0], "server") ||
3041 !strcmp(args[0], "default-server") ||
3042 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02003043 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3044 if (err_code & ERR_FATAL)
3045 goto out;
3046 }
3047 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003048 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003049 int cur_arg;
3050
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 if (curproxy == &defproxy) {
3052 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 }
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 Tarreaubaaee002006-06-26 02:48:02 +02003058
Willy Tarreau24709282013-03-10 21:32:12 +01003059 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003060 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003065
Willy Tarreaua261e9b2016-12-22 20:44:00 +01003066 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003067
3068 /* use default settings for unix sockets */
3069 bind_conf->ux.uid = global.unix_bind.ux.uid;
3070 bind_conf->ux.gid = global.unix_bind.ux.gid;
3071 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003072
3073 /* NOTE: the following line might create several listeners if there
3074 * are comma-separated IPs or port ranges. So all further processing
3075 * will have to be applied to all listeners created after last_listen.
3076 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003077 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3078 if (errmsg && *errmsg) {
3079 indent_msg(&errmsg, 2);
3080 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003081 }
3082 else
3083 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3084 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
3087 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003088
Willy Tarreau4348fad2012-09-20 16:48:07 +02003089 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3090 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003091 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003092 }
3093
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003094 cur_arg = 2;
3095 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003096 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003097 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003098 char *err;
3099
Willy Tarreau26982662012-09-12 23:17:10 +02003100 kw = bind_find_kw(args[cur_arg]);
3101 if (kw) {
3102 char *err = NULL;
3103 int code;
3104
3105 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003106 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3107 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003108 cur_arg += 1 + kw->skip ;
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
3112
Willy Tarreau4348fad2012-09-20 16:48:07 +02003113 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003114 err_code |= code;
3115
3116 if (code) {
3117 if (err && *err) {
3118 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003119 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003120 }
3121 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003122 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3123 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003124 if (code & ERR_FATAL) {
3125 free(err);
3126 cur_arg += 1 + kw->skip;
3127 goto out;
3128 }
3129 }
3130 free(err);
3131 cur_arg += 1 + kw->skip;
3132 continue;
3133 }
3134
Willy Tarreau8638f482012-09-18 18:01:17 +02003135 err = NULL;
3136 if (!bind_dumped) {
3137 bind_dump_kws(&err);
3138 indent_msg(&err, 4);
3139 bind_dumped = 1;
3140 }
3141
3142 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3143 file, linenum, args[0], args[1], args[cur_arg],
3144 err ? " Registered keywords :" : "", err ? err : "");
3145 free(err);
3146
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003149 }
Willy Tarreau93893792009-07-23 13:19:11 +02003150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 }
3152 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003153 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003159 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003161
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 /* flush useless bits */
3163 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003166 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003167 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003169
William Lallemanddf1425a2015-04-28 20:17:49 +02003170 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3171 goto out;
3172
Willy Tarreau1c47f852006-07-09 08:22:27 +02003173 if (!*args[1]) {
3174 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3175 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003178 }
3179
Willy Tarreaua534fea2008-08-03 12:19:50 +02003180 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003181 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003182 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003183 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003184 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3185
Willy Tarreau93893792009-07-23 13:19:11 +02003186 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003189 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3190 goto out;
3191
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3193 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3194 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3195 else {
3196 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003201 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003202 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003203
3204 if (curproxy == &defproxy) {
3205 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003209 }
3210
William Lallemanddf1425a2015-04-28 20:17:49 +02003211 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3212 goto out;
3213
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003214 if (!*args[1]) {
3215 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3216 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003219 }
3220
3221 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003222 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003223 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003224
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003225 if (curproxy->uuid <= 0) {
3226 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003227 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003230 }
3231
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003232 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3233 if (node) {
3234 struct proxy *target = container_of(node, struct proxy, conf.id);
3235 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3236 file, linenum, proxy_type_str(curproxy), curproxy->id,
3237 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
3241 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003242 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003243 else if (!strcmp(args[0], "description")) {
3244 int i, len=0;
3245 char *d;
3246
Cyril Bonté99ed3272010-01-24 23:29:44 +01003247 if (curproxy == &defproxy) {
3248 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3249 file, linenum, args[0]);
3250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
3252 }
3253
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003254 if (!*args[1]) {
3255 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3256 file, linenum, args[0]);
3257 return -1;
3258 }
3259
Willy Tarreau348acfe2014-04-14 15:00:39 +02003260 for (i = 1; *args[i]; i++)
3261 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003262
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003263 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003264 curproxy->desc = d;
3265
Willy Tarreau348acfe2014-04-14 15:00:39 +02003266 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3267 for (i = 2; *args[i]; i++)
3268 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003269
3270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003272 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 curproxy->state = PR_STSTOPPED;
3275 }
3276 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003277 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 curproxy->state = PR_STNEW;
3280 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003281 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3282 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003283 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003284
3285 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003286 unsigned int low, high;
3287
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003288 if (strcmp(args[cur_arg], "all") == 0) {
3289 set = 0;
3290 break;
3291 }
3292 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003293 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003294 }
3295 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003296 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003297 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003298 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003299 char *dash = strchr(args[cur_arg], '-');
3300
3301 low = high = str2uic(args[cur_arg]);
3302 if (dash)
3303 high = str2uic(dash + 1);
3304
3305 if (high < low) {
3306 unsigned int swap = low;
3307 low = high;
3308 high = swap;
3309 }
3310
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003311 if (low < 1 || high > LONGBITS) {
3312 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3313 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003316 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003317 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003318 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003319 }
3320 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003321 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3322 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003325 }
3326 cur_arg++;
3327 }
3328 curproxy->bind_proc = set;
3329 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003330 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003331 if (curproxy == &defproxy) {
3332 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003335 }
3336
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003337 err = invalid_char(args[1]);
3338 if (err) {
3339 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3340 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003342 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003343 }
3344
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003345 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003346 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3347 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003350 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003351 }
3352 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3353
3354 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3355 err_code |= ERR_WARN;
3356
3357 if (*(args[1]) == 0) {
3358 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3359 file, linenum, args[0]);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363 free(curproxy->dyncookie_key);
3364 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3367 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368
Willy Tarreau977b8e42006-12-29 14:19:17 +01003369 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003370 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003371
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 if (*(args[1]) == 0) {
3373 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3374 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003378
Willy Tarreau67402132012-05-31 20:40:20 +02003379 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003380 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003381 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003382 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 curproxy->cookie_name = strdup(args[1]);
3384 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003385
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 cur_arg = 2;
3387 while (*(args[cur_arg])) {
3388 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003389 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 }
3391 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003392 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003395 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 }
3397 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003398 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003401 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003403 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003404 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003407 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003409 else if (!strcmp(args[cur_arg], "httponly")) {
3410 curproxy->ck_opts |= PR_CK_HTTPONLY;
3411 }
3412 else if (!strcmp(args[cur_arg], "secure")) {
3413 curproxy->ck_opts |= PR_CK_SECURE;
3414 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003415 else if (!strcmp(args[cur_arg], "domain")) {
3416 if (!*args[cur_arg + 1]) {
3417 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3418 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003421 }
3422
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003423 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003424 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003425 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3426 " dots nor does not start with a dot."
3427 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003428 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003429 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003430 }
3431
3432 err = invalid_domainchar(args[cur_arg + 1]);
3433 if (err) {
3434 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3435 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003438 }
3439
Willy Tarreau68a897b2009-12-03 23:28:34 +01003440 if (!curproxy->cookie_domain) {
3441 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3442 } else {
3443 /* one domain was already specified, add another one by
3444 * building the string which will be returned along with
3445 * the cookie.
3446 */
3447 char *new_ptr;
3448 int new_len = strlen(curproxy->cookie_domain) +
3449 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3450 new_ptr = malloc(new_len);
3451 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3452 free(curproxy->cookie_domain);
3453 curproxy->cookie_domain = new_ptr;
3454 }
Willy Tarreau31936852010-10-06 16:59:56 +02003455 cur_arg++;
3456 }
3457 else if (!strcmp(args[cur_arg], "maxidle")) {
3458 unsigned int maxidle;
3459 const char *res;
3460
3461 if (!*args[cur_arg + 1]) {
3462 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3463 file, linenum, args[cur_arg]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467
3468 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3469 if (res) {
3470 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3471 file, linenum, *res, args[cur_arg]);
3472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
3475 curproxy->cookie_maxidle = maxidle;
3476 cur_arg++;
3477 }
3478 else if (!strcmp(args[cur_arg], "maxlife")) {
3479 unsigned int maxlife;
3480 const char *res;
3481
3482 if (!*args[cur_arg + 1]) {
3483 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3484 file, linenum, args[cur_arg]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488
3489 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3490 if (res) {
3491 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3492 file, linenum, *res, args[cur_arg]);
3493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
3495 }
3496 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003497 cur_arg++;
3498 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003499 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003500
3501 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3502 err_code |= ERR_WARN;
3503 curproxy->ck_opts |= PR_CK_DYNAMIC;
3504 }
3505
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003507 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 +02003508 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 }
3512 cur_arg++;
3513 }
Willy Tarreau67402132012-05-31 20:40:20 +02003514 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3516 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519
Willy Tarreau67402132012-05-31 20:40:20 +02003520 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003525
Willy Tarreau67402132012-05-31 20:40:20 +02003526 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003527 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3528 file, linenum);
3529 err_code |= ERR_ALERT | ERR_FATAL;
3530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003532 else if (!strcmp(args[0], "email-alert")) {
3533 if (*(args[1]) == 0) {
3534 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3535 file, linenum, args[0]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539
3540 if (!strcmp(args[1], "from")) {
3541 if (*(args[1]) == 0) {
3542 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3543 file, linenum, args[1]);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
3547 free(curproxy->email_alert.from);
3548 curproxy->email_alert.from = strdup(args[2]);
3549 }
3550 else if (!strcmp(args[1], "mailers")) {
3551 if (*(args[1]) == 0) {
3552 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3553 file, linenum, args[1]);
3554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
3556 }
3557 free(curproxy->email_alert.mailers.name);
3558 curproxy->email_alert.mailers.name = strdup(args[2]);
3559 }
3560 else if (!strcmp(args[1], "myhostname")) {
3561 if (*(args[1]) == 0) {
3562 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3563 file, linenum, args[1]);
3564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
3566 }
3567 free(curproxy->email_alert.myhostname);
3568 curproxy->email_alert.myhostname = strdup(args[2]);
3569 }
Simon Horman64e34162015-02-06 11:11:57 +09003570 else if (!strcmp(args[1], "level")) {
3571 curproxy->email_alert.level = get_log_level(args[2]);
3572 if (curproxy->email_alert.level < 0) {
3573 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3574 file, linenum, args[1], args[2]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578 }
Simon Horman9dc49962015-01-30 11:22:59 +09003579 else if (!strcmp(args[1], "to")) {
3580 if (*(args[1]) == 0) {
3581 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3582 file, linenum, args[1]);
3583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
3585 }
3586 free(curproxy->email_alert.to);
3587 curproxy->email_alert.to = strdup(args[2]);
3588 }
3589 else {
3590 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3591 file, linenum, args[1]);
3592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
3594 }
Simon Horman64e34162015-02-06 11:11:57 +09003595 /* Indicate that the email_alert is at least partially configured */
3596 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003597 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003598 else if (!strcmp(args[0], "external-check")) {
3599 if (*(args[1]) == 0) {
3600 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3601 file, linenum, args[0]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605
3606 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003607 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003608 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003609 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003610 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3611 file, linenum, args[1]);
3612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
3614 }
3615 free(curproxy->check_command);
3616 curproxy->check_command = strdup(args[2]);
3617 }
3618 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003619 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003620 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003621 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003622 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3623 file, linenum, args[1]);
3624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
3626 }
3627 free(curproxy->check_path);
3628 curproxy->check_path = strdup(args[2]);
3629 }
3630 else {
3631 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3632 file, linenum, args[1]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003637 else if (!strcmp(args[0], "persist")) { /* persist */
3638 if (*(args[1]) == 0) {
3639 Alert("parsing [%s:%d] : missing persist method.\n",
3640 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003643 }
3644
3645 if (!strncmp(args[1], "rdp-cookie", 10)) {
3646 curproxy->options2 |= PR_O2_RDPC_PRST;
3647
Emeric Brunb982a3d2010-01-04 15:45:53 +01003648 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003649 const char *beg, *end;
3650
3651 beg = args[1] + 11;
3652 end = strchr(beg, ')');
3653
William Lallemanddf1425a2015-04-28 20:17:49 +02003654 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3655 goto out;
3656
Emeric Brun647caf12009-06-30 17:57:00 +02003657 if (!end || end == beg) {
3658 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3659 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003662 }
3663
3664 free(curproxy->rdp_cookie_name);
3665 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3666 curproxy->rdp_cookie_len = end-beg;
3667 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003668 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003669 free(curproxy->rdp_cookie_name);
3670 curproxy->rdp_cookie_name = strdup("msts");
3671 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3672 }
3673 else { /* syntax */
3674 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3675 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003678 }
3679 }
3680 else {
3681 Alert("parsing [%s:%d] : unknown persist method.\n",
3682 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003685 }
3686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003688 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003692 else if (!strcmp(args[0], "load-server-state-from-file")) {
3693 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3694 err_code |= ERR_WARN;
3695 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3696 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3697 }
3698 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3699 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3700 }
3701 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3702 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3703 }
3704 else {
3705 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3706 file, linenum, args[0], args[1]);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710 }
3711 else if (!strcmp(args[0], "server-state-file-name")) {
3712 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3713 err_code |= ERR_WARN;
3714 if (*(args[1]) == 0) {
3715 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3716 file, linenum, args[0]);
3717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
3719 }
3720 else if (!strcmp(args[1], "use-backend-name"))
3721 curproxy->server_state_file_name = strdup(curproxy->id);
3722 else
3723 curproxy->server_state_file_name = strdup(args[1]);
3724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003728
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003730 if (curproxy == &defproxy) {
3731 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
3734 }
3735
William Lallemand1a748ae2015-05-19 16:37:23 +02003736 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3737 goto out;
3738
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 if (*(args[4]) == 0) {
3740 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3741 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_ALERT | ERR_FATAL;
3743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003745 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 curproxy->capture_name = strdup(args[2]);
3747 curproxy->capture_namelen = strlen(curproxy->capture_name);
3748 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003749 curproxy->to_log |= LW_COOKIE;
3750 }
3751 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3752 struct cap_hdr *hdr;
3753
3754 if (curproxy == &defproxy) {
3755 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 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003758 }
3759
William Lallemand1a748ae2015-05-19 16:37:23 +02003760 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3761 goto out;
3762
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3764 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3765 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 }
3769
Vincent Bernat02779b62016-04-03 13:48:43 +02003770 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 hdr->next = curproxy->req_cap;
3772 hdr->name = strdup(args[3]);
3773 hdr->namelen = strlen(args[3]);
3774 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003775 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 hdr->index = curproxy->nb_req_cap++;
3777 curproxy->req_cap = hdr;
3778 curproxy->to_log |= LW_REQHDR;
3779 }
3780 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3781 struct cap_hdr *hdr;
3782
3783 if (curproxy == &defproxy) {
3784 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 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 }
3788
William Lallemand1a748ae2015-05-19 16:37:23 +02003789 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3790 goto out;
3791
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3793 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3794 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003797 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003798 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 hdr->next = curproxy->rsp_cap;
3800 hdr->name = strdup(args[3]);
3801 hdr->namelen = strlen(args[3]);
3802 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003803 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 hdr->index = curproxy->nb_rsp_cap++;
3805 curproxy->rsp_cap = hdr;
3806 curproxy->to_log |= LW_RSPHDR;
3807 }
3808 else {
3809 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3810 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
3814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003816 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003818
William Lallemanddf1425a2015-04-28 20:17:49 +02003819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3820 goto out;
3821
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 if (*(args[1]) == 0) {
3823 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3824 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 }
3828 curproxy->conn_retries = atol(args[1]);
3829 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003830 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003831 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003832
3833 if (curproxy == &defproxy) {
3834 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
3837 }
3838
Willy Tarreau20b0de52012-12-24 15:45:22 +01003839 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003840 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003841 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3842 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3843 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3844 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003845 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 +01003846 file, linenum, args[0]);
3847 err_code |= ERR_WARN;
3848 }
3849
Willy Tarreauff011f22011-01-06 17:51:27 +01003850 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003851
Willy Tarreauff011f22011-01-06 17:51:27 +01003852 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003853 err_code |= ERR_ALERT | ERR_ABORT;
3854 goto out;
3855 }
3856
Willy Tarreau5002f572014-04-23 01:32:02 +02003857 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003858 err_code |= warnif_cond_conflicts(rule->cond,
3859 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3860 file, linenum);
3861
Willy Tarreauff011f22011-01-06 17:51:27 +01003862 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003863 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003864 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003865 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003866
3867 if (curproxy == &defproxy) {
3868 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
3871 }
3872
3873 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003874 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003875 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3876 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003877 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3878 file, linenum, args[0]);
3879 err_code |= ERR_WARN;
3880 }
3881
3882 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3883
3884 if (!rule) {
3885 err_code |= ERR_ALERT | ERR_ABORT;
3886 goto out;
3887 }
3888
3889 err_code |= warnif_cond_conflicts(rule->cond,
3890 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3891 file, linenum);
3892
3893 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3894 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003895 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3896 /* set the header name and length into the proxy structure */
3897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3898 err_code |= ERR_WARN;
3899
3900 if (!*args[1]) {
3901 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3902 file, linenum, args[0]);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906
3907 /* set the desired header name */
3908 free(curproxy->server_id_hdr_name);
3909 curproxy->server_id_hdr_name = strdup(args[1]);
3910 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3911 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003912 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003913 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003914
Willy Tarreaub099aca2008-10-12 17:26:37 +02003915 if (curproxy == &defproxy) {
3916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003919 }
3920
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003921 /* emulate "block" using "http-request block". Since these rules are supposed to
3922 * be processed before all http-request rules, we put them into their own list
3923 * and will insert them at the end.
3924 */
3925 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3926 if (!rule) {
3927 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003928 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003929 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003930 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3931 err_code |= warnif_cond_conflicts(rule->cond,
3932 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3933 file, linenum);
3934 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003935
3936 if (!already_warned(WARN_BLOCK_DEPRECATED))
3937 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]);
3938
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003939 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003940 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003941 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003942
Cyril Bonté99ed3272010-01-24 23:29:44 +01003943 if (curproxy == &defproxy) {
3944 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948
Willy Tarreaube4653b2015-05-28 15:26:58 +02003949 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003950 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3951 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003954 }
3955
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003956 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003957 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003958 err_code |= warnif_cond_conflicts(rule->cond,
3959 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3960 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003961 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003962 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003963 struct switching_rule *rule;
3964
Willy Tarreaub099aca2008-10-12 17:26:37 +02003965 if (curproxy == &defproxy) {
3966 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003969 }
3970
Willy Tarreau55ea7572007-06-17 19:56:27 +02003971 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003973
3974 if (*(args[1]) == 0) {
3975 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003978 }
3979
Willy Tarreauf51658d2014-04-23 01:21:56 +02003980 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003981 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003982 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3983 file, linenum, errmsg);
3984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
3986 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003987
Willy Tarreauf51658d2014-04-23 01:21:56 +02003988 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003989 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003990 else if (*args[2]) {
3991 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3992 file, linenum, args[2]);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003996
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003997 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003998 if (!rule) {
3999 Alert("Out of memory error.\n");
4000 goto out;
4001 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004002 rule->cond = cond;
4003 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01004004 rule->line = linenum;
4005 rule->file = strdup(file);
4006 if (!rule->file) {
4007 Alert("Out of memory error.\n");
4008 goto out;
4009 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004010 LIST_INIT(&rule->list);
4011 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4012 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004013 else if (strcmp(args[0], "use-server") == 0) {
4014 struct server_rule *rule;
4015
4016 if (curproxy == &defproxy) {
4017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021
4022 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4023 err_code |= ERR_WARN;
4024
4025 if (*(args[1]) == 0) {
4026 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
4029 }
4030
4031 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4032 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4033 file, linenum, args[0]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004038 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004039 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4040 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004045 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004046
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004047 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004048 rule->cond = cond;
4049 rule->srv.name = strdup(args[1]);
4050 LIST_INIT(&rule->list);
4051 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4052 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4053 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004054 else if ((!strcmp(args[0], "force-persist")) ||
4055 (!strcmp(args[0], "ignore-persist"))) {
4056 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004057
4058 if (curproxy == &defproxy) {
4059 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063
4064 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4065 err_code |= ERR_WARN;
4066
Willy Tarreauef6494c2010-01-28 17:12:36 +01004067 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004068 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4069 file, linenum, args[0]);
4070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
4072 }
4073
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004074 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004075 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4076 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004081 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4082 * where force-persist is applied.
4083 */
4084 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004085
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004086 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004087 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004088 if (!strcmp(args[0], "force-persist")) {
4089 rule->type = PERSIST_TYPE_FORCE;
4090 } else {
4091 rule->type = PERSIST_TYPE_IGNORE;
4092 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004093 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004094 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004095 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004096 else if (!strcmp(args[0], "stick-table")) {
4097 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004098 struct proxy *other;
4099
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004100 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004101 if (other) {
4102 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4103 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004107
Emeric Brun32da3c42010-09-23 18:39:19 +02004108 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004109 curproxy->table.type = (unsigned int)-1;
4110 while (*args[myidx]) {
4111 const char *err;
4112
4113 if (strcmp(args[myidx], "size") == 0) {
4114 myidx++;
4115 if (!*(args[myidx])) {
4116 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4117 file, linenum, args[myidx-1]);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4122 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4123 file, linenum, *err, args[myidx-1]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004127 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004128 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004129 else if (strcmp(args[myidx], "peers") == 0) {
4130 myidx++;
Godbach50523162013-12-11 19:48:57 +08004131 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004132 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4133 file, linenum, args[myidx-1]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Godbach50523162013-12-11 19:48:57 +08004136 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004137 curproxy->table.peers.name = strdup(args[myidx++]);
4138 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004139 else if (strcmp(args[myidx], "expire") == 0) {
4140 myidx++;
4141 if (!*(args[myidx])) {
4142 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4143 file, linenum, args[myidx-1]);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4148 if (err) {
4149 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4150 file, linenum, *err, args[myidx-1]);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004154 if (val > INT_MAX) {
4155 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4156 file, linenum, val);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004160 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004161 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004162 }
4163 else if (strcmp(args[myidx], "nopurge") == 0) {
4164 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004165 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004166 }
4167 else if (strcmp(args[myidx], "type") == 0) {
4168 myidx++;
4169 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4170 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4171 file, linenum, args[myidx]);
4172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
4174 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004175 /* myidx already points to next arg */
4176 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004177 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004178 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004179 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004180
4181 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004182 nw = args[myidx];
4183 while (*nw) {
4184 /* the "store" keyword supports a comma-separated list */
4185 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004186 sa = NULL; /* store arg */
4187 while (*nw && *nw != ',') {
4188 if (*nw == '(') {
4189 *nw = 0;
4190 sa = ++nw;
4191 while (*nw != ')') {
4192 if (!*nw) {
4193 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4194 file, linenum, args[0], cw);
4195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
4197 }
4198 nw++;
4199 }
4200 *nw = '\0';
4201 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004202 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004203 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004204 if (*nw)
4205 *nw++ = '\0';
4206 type = stktable_get_data_type(cw);
4207 if (type < 0) {
4208 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4209 file, linenum, args[0], cw);
4210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
4212 }
Willy Tarreauac782882010-06-20 10:41:54 +02004213
4214 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4215 switch (err) {
4216 case PE_NONE: break;
4217 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004218 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4219 file, linenum, args[0], cw);
4220 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004221 break;
4222
4223 case PE_ARG_MISSING:
4224 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4225 file, linenum, args[0], cw);
4226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
4228
4229 case PE_ARG_NOT_USED:
4230 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4231 file, linenum, args[0], cw);
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234
4235 default:
4236 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4237 file, linenum, args[0], cw);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004240 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004241 }
4242 myidx++;
4243 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004244 else {
4245 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4246 file, linenum, args[myidx]);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004249 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004250 }
4251
4252 if (!curproxy->table.size) {
4253 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4254 file, linenum);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
4259 if (curproxy->table.type == (unsigned int)-1) {
4260 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4261 file, linenum);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265 }
4266 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004267 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004268 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004269 int myidx = 0;
4270 const char *name = NULL;
4271 int flags;
4272
4273 if (curproxy == &defproxy) {
4274 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
4278
4279 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4280 err_code |= ERR_WARN;
4281 goto out;
4282 }
4283
4284 myidx++;
4285 if ((strcmp(args[myidx], "store") == 0) ||
4286 (strcmp(args[myidx], "store-request") == 0)) {
4287 myidx++;
4288 flags = STK_IS_STORE;
4289 }
4290 else if (strcmp(args[myidx], "store-response") == 0) {
4291 myidx++;
4292 flags = STK_IS_STORE | STK_ON_RSP;
4293 }
4294 else if (strcmp(args[myidx], "match") == 0) {
4295 myidx++;
4296 flags = STK_IS_MATCH;
4297 }
4298 else if (strcmp(args[myidx], "on") == 0) {
4299 myidx++;
4300 flags = STK_IS_MATCH | STK_IS_STORE;
4301 }
4302 else {
4303 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307
4308 if (*(args[myidx]) == 0) {
4309 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004314 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004315 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004316 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004317 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321
4322 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004323 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4324 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4325 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004326 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004327 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004328 goto out;
4329 }
4330 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004331 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4332 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4333 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004334 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004335 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004336 goto out;
4337 }
4338 }
4339
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004340 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004341 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004342
Emeric Brunb982a3d2010-01-04 15:45:53 +01004343 if (strcmp(args[myidx], "table") == 0) {
4344 myidx++;
4345 name = args[myidx++];
4346 }
4347
Willy Tarreauef6494c2010-01-28 17:12:36 +01004348 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004349 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004350 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4351 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004352 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004353 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004354 goto out;
4355 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004356 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004357 else if (*(args[myidx])) {
4358 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4359 file, linenum, args[0], args[myidx]);
4360 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004361 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004362 goto out;
4363 }
Emeric Brun97679e72010-09-23 17:56:44 +02004364 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004365 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004366 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004367 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004368
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004369 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004370 rule->cond = cond;
4371 rule->expr = expr;
4372 rule->flags = flags;
4373 rule->table.name = name ? strdup(name) : NULL;
4374 LIST_INIT(&rule->list);
4375 if (flags & STK_ON_RSP)
4376 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4377 else
4378 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 else if (!strcmp(args[0], "stats")) {
4381 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4382 curproxy->uri_auth = NULL; /* we must detach from the default config */
4383
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004384 if (!*args[1]) {
4385 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004386 } else if (!strcmp(args[1], "admin")) {
4387 struct stats_admin_rule *rule;
4388
4389 if (curproxy == &defproxy) {
4390 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
4394
4395 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4396 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4397 err_code |= ERR_ALERT | ERR_ABORT;
4398 goto out;
4399 }
4400
4401 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4402 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4403 file, linenum, args[0], args[1]);
4404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
4406 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004407 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004408 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4409 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
4412 }
4413
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004414 err_code |= warnif_cond_conflicts(cond,
4415 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4416 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004417
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004418 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004419 rule->cond = cond;
4420 LIST_INIT(&rule->list);
4421 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 } else if (!strcmp(args[1], "uri")) {
4423 if (*(args[2]) == 0) {
4424 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4428 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_ABORT;
4430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
4432 } else if (!strcmp(args[1], "realm")) {
4433 if (*(args[2]) == 0) {
4434 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4438 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_ABORT;
4440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004442 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004443 unsigned interval;
4444
4445 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4446 if (err) {
4447 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4448 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004451 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4452 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_ABORT;
4454 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004455 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004456 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004457 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004458
4459 if (curproxy == &defproxy) {
4460 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
4464
4465 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4466 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4467 err_code |= ERR_ALERT | ERR_ABORT;
4468 goto out;
4469 }
4470
Willy Tarreauff011f22011-01-06 17:51:27 +01004471 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004472 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004473 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4474 file, linenum, args[0]);
4475 err_code |= ERR_WARN;
4476 }
4477
Willy Tarreauff011f22011-01-06 17:51:27 +01004478 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004479
Willy Tarreauff011f22011-01-06 17:51:27 +01004480 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004481 err_code |= ERR_ALERT | ERR_ABORT;
4482 goto out;
4483 }
4484
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004485 err_code |= warnif_cond_conflicts(rule->cond,
4486 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4487 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004488 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004489
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 } else if (!strcmp(args[1], "auth")) {
4491 if (*(args[2]) == 0) {
4492 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4496 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004497 err_code |= ERR_ALERT | ERR_ABORT;
4498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 }
4500 } else if (!strcmp(args[1], "scope")) {
4501 if (*(args[2]) == 0) {
4502 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4506 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_ABORT;
4508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 }
4510 } else if (!strcmp(args[1], "enable")) {
4511 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4512 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004513 err_code |= ERR_ALERT | ERR_ABORT;
4514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004516 } else if (!strcmp(args[1], "hide-version")) {
4517 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4518 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_ALERT | ERR_ABORT;
4520 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004521 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004522 } else if (!strcmp(args[1], "show-legends")) {
4523 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4524 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4525 err_code |= ERR_ALERT | ERR_ABORT;
4526 goto out;
4527 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004528 } else if (!strcmp(args[1], "show-node")) {
4529
4530 if (*args[2]) {
4531 int i;
4532 char c;
4533
4534 for (i=0; args[2][i]; i++) {
4535 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004536 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4537 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004538 break;
4539 }
4540
4541 if (!i || args[2][i]) {
4542 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4543 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4544 file, linenum, args[0], args[1]);
4545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
4547 }
4548 }
4549
4550 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4551 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4552 err_code |= ERR_ALERT | ERR_ABORT;
4553 goto out;
4554 }
4555 } else if (!strcmp(args[1], "show-desc")) {
4556 char *desc = NULL;
4557
4558 if (*args[2]) {
4559 int i, len=0;
4560 char *d;
4561
Willy Tarreau348acfe2014-04-14 15:00:39 +02004562 for (i = 2; *args[i]; i++)
4563 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004564
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004565 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004566
Willy Tarreau348acfe2014-04-14 15:00:39 +02004567 d += snprintf(d, desc + len - d, "%s", args[2]);
4568 for (i = 3; *args[i]; i++)
4569 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004570 }
4571
4572 if (!*args[2] && !global.desc)
4573 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4574 file, linenum, args[1]);
4575 else {
4576 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4577 free(desc);
4578 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4579 err_code |= ERR_ALERT | ERR_ABORT;
4580 goto out;
4581 }
4582 free(desc);
4583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004585stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004586 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 +01004587 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
4591 }
4592 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004593 int optnum;
4594
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004595 if (*(args[1]) == '\0') {
4596 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004601
4602 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4603 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004604 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4605 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4606 file, linenum, cfg_opts[optnum].name);
4607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004610 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4611 goto out;
4612
Willy Tarreau93893792009-07-23 13:19:11 +02004613 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4614 err_code |= ERR_WARN;
4615 goto out;
4616 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004617
Willy Tarreau3842f002009-06-14 11:39:52 +02004618 curproxy->no_options &= ~cfg_opts[optnum].val;
4619 curproxy->options &= ~cfg_opts[optnum].val;
4620
4621 switch (kwm) {
4622 case KWM_STD:
4623 curproxy->options |= cfg_opts[optnum].val;
4624 break;
4625 case KWM_NO:
4626 curproxy->no_options |= cfg_opts[optnum].val;
4627 break;
4628 case KWM_DEF: /* already cleared */
4629 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004630 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004631
Willy Tarreau93893792009-07-23 13:19:11 +02004632 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004633 }
4634 }
4635
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004636 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4637 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004638 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4639 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4640 file, linenum, cfg_opts2[optnum].name);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004644 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4645 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004646 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4647 err_code |= ERR_WARN;
4648 goto out;
4649 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004650
Willy Tarreau3842f002009-06-14 11:39:52 +02004651 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4652 curproxy->options2 &= ~cfg_opts2[optnum].val;
4653
4654 switch (kwm) {
4655 case KWM_STD:
4656 curproxy->options2 |= cfg_opts2[optnum].val;
4657 break;
4658 case KWM_NO:
4659 curproxy->no_options2 |= cfg_opts2[optnum].val;
4660 break;
4661 case KWM_DEF: /* already cleared */
4662 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004663 }
Willy Tarreau93893792009-07-23 13:19:11 +02004664 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004665 }
4666 }
4667
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004668 /* HTTP options override each other. They can be cancelled using
4669 * "no option xxx" which only switches to default mode if the mode
4670 * was this one (useful for cancelling options set in defaults
4671 * sections).
4672 */
4673 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004674 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4675 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004676 if (kwm == KWM_STD) {
4677 curproxy->options &= ~PR_O_HTTP_MODE;
4678 curproxy->options |= PR_O_HTTP_PCL;
4679 goto out;
4680 }
4681 else if (kwm == KWM_NO) {
4682 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4683 curproxy->options &= ~PR_O_HTTP_MODE;
4684 goto out;
4685 }
4686 }
4687 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004688 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4689 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004690 if (kwm == KWM_STD) {
4691 curproxy->options &= ~PR_O_HTTP_MODE;
4692 curproxy->options |= PR_O_HTTP_FCL;
4693 goto out;
4694 }
4695 else if (kwm == KWM_NO) {
4696 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4697 curproxy->options &= ~PR_O_HTTP_MODE;
4698 goto out;
4699 }
4700 }
4701 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004702 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4703 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004704 if (kwm == KWM_STD) {
4705 curproxy->options &= ~PR_O_HTTP_MODE;
4706 curproxy->options |= PR_O_HTTP_SCL;
4707 goto out;
4708 }
4709 else if (kwm == KWM_NO) {
4710 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4711 curproxy->options &= ~PR_O_HTTP_MODE;
4712 goto out;
4713 }
4714 }
4715 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004716 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4717 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004718 if (kwm == KWM_STD) {
4719 curproxy->options &= ~PR_O_HTTP_MODE;
4720 curproxy->options |= PR_O_HTTP_KAL;
4721 goto out;
4722 }
4723 else if (kwm == KWM_NO) {
4724 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4725 curproxy->options &= ~PR_O_HTTP_MODE;
4726 goto out;
4727 }
4728 }
4729 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004730 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4731 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004732 if (kwm == KWM_STD) {
4733 curproxy->options &= ~PR_O_HTTP_MODE;
4734 curproxy->options |= PR_O_HTTP_TUN;
4735 goto out;
4736 }
4737 else if (kwm == KWM_NO) {
4738 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4739 curproxy->options &= ~PR_O_HTTP_MODE;
4740 goto out;
4741 }
4742 }
4743
Joseph Lynch726ab712015-05-11 23:25:34 -07004744 /* Redispatch can take an integer argument that control when the
4745 * resispatch occurs. All values are relative to the retries option.
4746 * This can be cancelled using "no option xxx".
4747 */
4748 if (strcmp(args[1], "redispatch") == 0) {
4749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4750 err_code |= ERR_WARN;
4751 goto out;
4752 }
4753
4754 curproxy->no_options &= ~PR_O_REDISP;
4755 curproxy->options &= ~PR_O_REDISP;
4756
4757 switch (kwm) {
4758 case KWM_STD:
4759 curproxy->options |= PR_O_REDISP;
4760 curproxy->redispatch_after = -1;
4761 if(*args[2]) {
4762 curproxy->redispatch_after = atol(args[2]);
4763 }
4764 break;
4765 case KWM_NO:
4766 curproxy->no_options |= PR_O_REDISP;
4767 curproxy->redispatch_after = 0;
4768 break;
4769 case KWM_DEF: /* already cleared */
4770 break;
4771 }
4772 goto out;
4773 }
4774
Willy Tarreau3842f002009-06-14 11:39:52 +02004775 if (kwm != KWM_STD) {
4776 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004777 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004780 }
4781
Emeric Brun3a058f32009-06-30 18:26:00 +02004782 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004783 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004785 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004786 if (*(args[2]) != '\0') {
4787 if (!strcmp(args[2], "clf")) {
4788 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004789 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004790 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004791 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004794 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004795 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4796 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004797 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004798 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4799 char *oldlogformat = "log-format";
4800 char *clflogformat = "";
4801
4802 if (curproxy->conf.logformat_string == default_http_log_format)
4803 oldlogformat = "option httplog";
4804 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4805 oldlogformat = "option tcplog";
4806 else if (curproxy->conf.logformat_string == clf_http_log_format)
4807 oldlogformat = "option httplog clf";
4808 if (logformat == clf_http_log_format)
4809 clflogformat = " clf";
4810 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4811 file, linenum, clflogformat, oldlogformat);
4812 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004813 if (curproxy->conf.logformat_string != default_http_log_format &&
4814 curproxy->conf.logformat_string != default_tcp_log_format &&
4815 curproxy->conf.logformat_string != clf_http_log_format)
4816 free(curproxy->conf.logformat_string);
4817 curproxy->conf.logformat_string = logformat;
4818
4819 free(curproxy->conf.lfs_file);
4820 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4821 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004822 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004823 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004824 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4825 char *oldlogformat = "log-format";
4826
4827 if (curproxy->conf.logformat_string == default_http_log_format)
4828 oldlogformat = "option httplog";
4829 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4830 oldlogformat = "option tcplog";
4831 else if (curproxy->conf.logformat_string == clf_http_log_format)
4832 oldlogformat = "option httplog clf";
4833 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4834 file, linenum, oldlogformat);
4835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004837 if (curproxy->conf.logformat_string != default_http_log_format &&
4838 curproxy->conf.logformat_string != default_tcp_log_format &&
4839 curproxy->conf.logformat_string != clf_http_log_format)
4840 free(curproxy->conf.logformat_string);
4841 curproxy->conf.logformat_string = default_tcp_log_format;
4842
4843 free(curproxy->conf.lfs_file);
4844 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4845 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004846
4847 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4848 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004849 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004851 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004852 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004853 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004854
William Lallemanddf1425a2015-04-28 20:17:49 +02004855 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4856 goto out;
4857
Willy Tarreau13943ab2006-12-31 00:24:10 +01004858 if (curproxy->cap & PR_CAP_FE)
4859 curproxy->options |= PR_O_TCP_CLI_KA;
4860 if (curproxy->cap & PR_CAP_BE)
4861 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
4863 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004865 err_code |= ERR_WARN;
4866
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004868 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004869 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004870 curproxy->options2 &= ~PR_O2_CHK_ANY;
4871 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 if (!*args[2]) { /* no argument */
4873 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4874 curproxy->check_len = strlen(DEF_CHECK_REQ);
4875 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004876 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004877 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004879 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004881 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 if (*args[4])
4883 reqlen += strlen(args[4]);
4884 else
4885 reqlen += strlen("HTTP/1.0");
4886
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004887 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004888 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004889 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004891 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4892 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004893 }
4894 else if (!strcmp(args[1], "ssl-hello-chk")) {
4895 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004896 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004897 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004898
Willy Tarreaua534fea2008-08-03 12:19:50 +02004899 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004900 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004901 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004902 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004903
4904 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
Willy Tarreau23677902007-05-08 23:50:35 +02004907 else if (!strcmp(args[1], "smtpchk")) {
4908 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004909 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004910 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004911 curproxy->options2 &= ~PR_O2_CHK_ANY;
4912 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004913
4914 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4915 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4916 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4917 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4918 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4919 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004920 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004921 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4922 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4923 } else {
4924 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4925 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4926 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4927 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4928 }
4929 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004930 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4931 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004932 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004933 else if (!strcmp(args[1], "pgsql-check")) {
4934 /* use PostgreSQL request to check servers' health */
4935 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4936 err_code |= ERR_WARN;
4937
4938 free(curproxy->check_req);
4939 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004940 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004941 curproxy->options2 |= PR_O2_PGSQL_CHK;
4942
4943 if (*(args[2])) {
4944 int cur_arg = 2;
4945
4946 while (*(args[cur_arg])) {
4947 if (strcmp(args[cur_arg], "user") == 0) {
4948 char * packet;
4949 uint32_t packet_len;
4950 uint32_t pv;
4951
4952 /* suboption header - needs additional argument for it */
4953 if (*(args[cur_arg+1]) == 0) {
4954 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4955 file, linenum, args[0], args[1], args[cur_arg]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
4959
4960 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4961 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4962 pv = htonl(0x30000); /* protocol version 3.0 */
4963
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004964 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004965
4966 memcpy(packet + 4, &pv, 4);
4967
4968 /* copy "user" */
4969 memcpy(packet + 8, "user", 4);
4970
4971 /* copy username */
4972 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4973
4974 free(curproxy->check_req);
4975 curproxy->check_req = packet;
4976 curproxy->check_len = packet_len;
4977
4978 packet_len = htonl(packet_len);
4979 memcpy(packet, &packet_len, 4);
4980 cur_arg += 2;
4981 } else {
4982 /* unknown suboption - catchall */
4983 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4984 file, linenum, args[0], args[1]);
4985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988 } /* end while loop */
4989 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004990 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4991 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004992 }
4993
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004994 else if (!strcmp(args[1], "redis-check")) {
4995 /* use REDIS PING request to check servers' health */
4996 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4997 err_code |= ERR_WARN;
4998
4999 free(curproxy->check_req);
5000 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005001 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02005002 curproxy->options2 |= PR_O2_REDIS_CHK;
5003
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005004 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02005005 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
5006 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005007
5008 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5009 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02005010 }
5011
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005012 else if (!strcmp(args[1], "mysql-check")) {
5013 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5015 err_code |= ERR_WARN;
5016
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005017 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01005018 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005019 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005020 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005021
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005022 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005023 * const char mysql40_client_auth_pkt[] = {
5024 * "\x0e\x00\x00" // packet length
5025 * "\x01" // packet number
5026 * "\x00\x00" // client capabilities
5027 * "\x00\x00\x01" // max packet
5028 * "haproxy\x00" // username (null terminated string)
5029 * "\x00" // filler (always 0x00)
5030 * "\x01\x00\x00" // packet length
5031 * "\x00" // packet number
5032 * "\x01" // COM_QUIT command
5033 * };
5034 */
5035
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005036 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5037 * const char mysql41_client_auth_pkt[] = {
5038 * "\x0e\x00\x00\" // packet length
5039 * "\x01" // packet number
5040 * "\x00\x00\x00\x00" // client capabilities
5041 * "\x00\x00\x00\x01" // max packet
5042 * "\x21" // character set (UTF-8)
5043 * char[23] // All zeroes
5044 * "haproxy\x00" // username (null terminated string)
5045 * "\x00" // filler (always 0x00)
5046 * "\x01\x00\x00" // packet length
5047 * "\x00" // packet number
5048 * "\x01" // COM_QUIT command
5049 * };
5050 */
5051
5052
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005053 if (*(args[2])) {
5054 int cur_arg = 2;
5055
5056 while (*(args[cur_arg])) {
5057 if (strcmp(args[cur_arg], "user") == 0) {
5058 char *mysqluser;
5059 int packetlen, reqlen, userlen;
5060
5061 /* suboption header - needs additional argument for it */
5062 if (*(args[cur_arg+1]) == 0) {
5063 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5064 file, linenum, args[0], args[1], args[cur_arg]);
5065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
5067 }
5068 mysqluser = args[cur_arg + 1];
5069 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005070
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005071 if (*(args[cur_arg+2])) {
5072 if (!strcmp(args[cur_arg+2], "post-41")) {
5073 packetlen = userlen + 7 + 27;
5074 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005075
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005076 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005077 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005078 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005079
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005080 snprintf(curproxy->check_req, 4, "%c%c%c",
5081 ((unsigned char) packetlen & 0xff),
5082 ((unsigned char) (packetlen >> 8) & 0xff),
5083 ((unsigned char) (packetlen >> 16) & 0xff));
5084
5085 curproxy->check_req[3] = 1;
5086 curproxy->check_req[5] = 130;
5087 curproxy->check_req[11] = 1;
5088 curproxy->check_req[12] = 33;
5089 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5090 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5091 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5092 cur_arg += 3;
5093 } else {
5094 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
5097 }
5098 } else {
5099 packetlen = userlen + 7;
5100 reqlen = packetlen + 9;
5101
5102 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005103 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005104 curproxy->check_len = reqlen;
5105
5106 snprintf(curproxy->check_req, 4, "%c%c%c",
5107 ((unsigned char) packetlen & 0xff),
5108 ((unsigned char) (packetlen >> 8) & 0xff),
5109 ((unsigned char) (packetlen >> 16) & 0xff));
5110
5111 curproxy->check_req[3] = 1;
5112 curproxy->check_req[5] = 128;
5113 curproxy->check_req[8] = 1;
5114 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5115 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5116 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5117 cur_arg += 2;
5118 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005119 } else {
5120 /* unknown suboption - catchall */
5121 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5122 file, linenum, args[0], args[1]);
5123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
5125 }
5126 } /* end while loop */
5127 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005128 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005129 else if (!strcmp(args[1], "ldap-check")) {
5130 /* use LDAP request to check servers' health */
5131 free(curproxy->check_req);
5132 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005133 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005134 curproxy->options2 |= PR_O2_LDAP_CHK;
5135
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005136 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005137 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5138 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005139 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5140 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005141 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005142 else if (!strcmp(args[1], "spop-check")) {
5143 if (curproxy == &defproxy) {
5144 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5145 file, linenum, args[0], args[1]);
5146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
5148 }
5149 if (curproxy->cap & PR_CAP_FE) {
5150 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5151 file, linenum, args[0], args[1]);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
5155
5156 /* use SPOE request to check servers' health */
5157 free(curproxy->check_req);
5158 curproxy->check_req = NULL;
5159 curproxy->options2 &= ~PR_O2_CHK_ANY;
5160 curproxy->options2 |= PR_O2_SPOP_CHK;
5161
Christopher Faulet8ef75252017-02-20 22:56:03 +01005162 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005163 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
5166 }
5167 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5168 goto out;
5169 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005170 else if (!strcmp(args[1], "tcp-check")) {
5171 /* use raw TCPCHK send/expect to check servers' health */
5172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5173 err_code |= ERR_WARN;
5174
5175 free(curproxy->check_req);
5176 curproxy->check_req = NULL;
5177 curproxy->options2 &= ~PR_O2_CHK_ANY;
5178 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005179 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5180 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005181 }
Simon Horman98637e52014-06-20 12:30:16 +09005182 else if (!strcmp(args[1], "external-check")) {
5183 /* excute an external command to check servers' health */
5184 free(curproxy->check_req);
5185 curproxy->check_req = NULL;
5186 curproxy->options2 &= ~PR_O2_CHK_ANY;
5187 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005188 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5189 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005190 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005191 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005192 int cur_arg;
5193
5194 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5195 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005196 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005197
Willy Tarreau87cf5142011-08-19 22:57:24 +02005198 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005199
5200 free(curproxy->fwdfor_hdr_name);
5201 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5202 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5203
5204 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5205 cur_arg = 2;
5206 while (*(args[cur_arg])) {
5207 if (!strcmp(args[cur_arg], "except")) {
5208 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005209 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005210 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5211 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005214 }
5215 /* flush useless bits */
5216 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005217 cur_arg += 2;
5218 } else if (!strcmp(args[cur_arg], "header")) {
5219 /* suboption header - needs additional argument for it */
5220 if (*(args[cur_arg+1]) == 0) {
5221 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5222 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005225 }
5226 free(curproxy->fwdfor_hdr_name);
5227 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5228 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5229 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005230 } else if (!strcmp(args[cur_arg], "if-none")) {
5231 curproxy->options &= ~PR_O_FF_ALWAYS;
5232 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005233 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005234 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005235 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005236 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005239 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005240 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005241 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005242 else if (!strcmp(args[1], "originalto")) {
5243 int cur_arg;
5244
5245 /* insert x-original-to field, but not for the IP address listed as an except.
5246 * set default options (ie: bitfield, header name, etc)
5247 */
5248
5249 curproxy->options |= PR_O_ORGTO;
5250
5251 free(curproxy->orgto_hdr_name);
5252 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5253 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5254
Willy Tarreau87cf5142011-08-19 22:57:24 +02005255 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005256 cur_arg = 2;
5257 while (*(args[cur_arg])) {
5258 if (!strcmp(args[cur_arg], "except")) {
5259 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005260 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 +02005261 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5262 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005265 }
5266 /* flush useless bits */
5267 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5268 cur_arg += 2;
5269 } else if (!strcmp(args[cur_arg], "header")) {
5270 /* suboption header - needs additional argument for it */
5271 if (*(args[cur_arg+1]) == 0) {
5272 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5273 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005274 err_code |= ERR_ALERT | ERR_FATAL;
5275 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005276 }
5277 free(curproxy->orgto_hdr_name);
5278 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5279 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5280 cur_arg += 2;
5281 } else {
5282 /* unknown suboption - catchall */
5283 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5284 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005287 }
5288 } /* end while loop */
5289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005290 else {
5291 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294 }
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005297 else if (!strcmp(args[0], "default_backend")) {
5298 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005300
5301 if (*(args[1]) == 0) {
5302 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005305 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005306 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005307 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005308
5309 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5310 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005311 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005313 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005315
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005316 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5317 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 +01005318 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005319 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 /* enable reconnections to dispatch */
5321 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005322
5323 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005326 else if (!strcmp(args[0], "http-reuse")) {
5327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5328 err_code |= ERR_WARN;
5329
5330 if (strcmp(args[1], "never") == 0) {
5331 /* enable a graceful server shutdown on an HTTP 404 response */
5332 curproxy->options &= ~PR_O_REUSE_MASK;
5333 curproxy->options |= PR_O_REUSE_NEVR;
5334 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5335 goto out;
5336 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005337 else if (strcmp(args[1], "safe") == 0) {
5338 /* enable a graceful server shutdown on an HTTP 404 response */
5339 curproxy->options &= ~PR_O_REUSE_MASK;
5340 curproxy->options |= PR_O_REUSE_SAFE;
5341 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5342 goto out;
5343 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005344 else if (strcmp(args[1], "aggressive") == 0) {
5345 curproxy->options &= ~PR_O_REUSE_MASK;
5346 curproxy->options |= PR_O_REUSE_AGGR;
5347 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5348 goto out;
5349 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005350 else if (strcmp(args[1], "always") == 0) {
5351 /* enable a graceful server shutdown on an HTTP 404 response */
5352 curproxy->options &= ~PR_O_REUSE_MASK;
5353 curproxy->options |= PR_O_REUSE_ALWS;
5354 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5355 goto out;
5356 }
5357 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005358 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 }
5362 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005363 else if (!strcmp(args[0], "http-check")) {
5364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005365 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005366
5367 if (strcmp(args[1], "disable-on-404") == 0) {
5368 /* enable a graceful server shutdown on an HTTP 404 response */
5369 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005370 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5371 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005372 }
Willy Tarreauef781042010-01-27 11:53:01 +01005373 else if (strcmp(args[1], "send-state") == 0) {
5374 /* enable emission of the apparent state of a server in HTTP checks */
5375 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005376 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5377 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005378 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005379 else if (strcmp(args[1], "expect") == 0) {
5380 const char *ptr_arg;
5381 int cur_arg;
5382
5383 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5384 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387 }
5388
5389 cur_arg = 2;
5390 /* consider exclamation marks, sole or at the beginning of a word */
5391 while (*(ptr_arg = args[cur_arg])) {
5392 while (*ptr_arg == '!') {
5393 curproxy->options2 ^= PR_O2_EXP_INV;
5394 ptr_arg++;
5395 }
5396 if (*ptr_arg)
5397 break;
5398 cur_arg++;
5399 }
5400 /* now ptr_arg points to the beginning of a word past any possible
5401 * exclamation mark, and cur_arg is the argument which holds this word.
5402 */
5403 if (strcmp(ptr_arg, "status") == 0) {
5404 if (!*(args[cur_arg + 1])) {
5405 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5406 file, linenum, args[0], args[1], ptr_arg);
5407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
5409 }
5410 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005411 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005412 curproxy->expect_str = strdup(args[cur_arg + 1]);
5413 }
5414 else if (strcmp(ptr_arg, "string") == 0) {
5415 if (!*(args[cur_arg + 1])) {
5416 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5417 file, linenum, args[0], args[1], ptr_arg);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005422 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005423 curproxy->expect_str = strdup(args[cur_arg + 1]);
5424 }
5425 else if (strcmp(ptr_arg, "rstatus") == 0) {
5426 if (!*(args[cur_arg + 1])) {
5427 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5428 file, linenum, args[0], args[1], ptr_arg);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005433 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005434 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005435 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005436 free(curproxy->expect_regex);
5437 curproxy->expect_regex = NULL;
5438 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005439 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005440 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5441 error = NULL;
5442 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5443 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5444 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5445 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
5449 }
5450 else if (strcmp(ptr_arg, "rstring") == 0) {
5451 if (!*(args[cur_arg + 1])) {
5452 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5453 file, linenum, args[0], args[1], ptr_arg);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005458 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005459 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005460 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005461 free(curproxy->expect_regex);
5462 curproxy->expect_regex = NULL;
5463 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005464 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005465 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5466 error = NULL;
5467 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5468 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5469 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5470 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005471 err_code |= ERR_ALERT | ERR_FATAL;
5472 goto out;
5473 }
5474 }
5475 else {
5476 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5477 file, linenum, args[0], args[1], ptr_arg);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
5481 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005482 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005483 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 +02005484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005486 }
5487 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005488 else if (!strcmp(args[0], "tcp-check")) {
5489 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5490 err_code |= ERR_WARN;
5491
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005492 if (strcmp(args[1], "comment") == 0) {
5493 int cur_arg;
5494 struct tcpcheck_rule *tcpcheck;
5495
5496 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005497 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005498 tcpcheck->action = TCPCHK_ACT_COMMENT;
5499
5500 if (!*args[cur_arg + 1]) {
5501 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5502 file, linenum, args[cur_arg]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
5506
5507 tcpcheck->comment = strdup(args[cur_arg + 1]);
5508
5509 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005510 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5511 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005512 }
5513 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005514 const char *ptr_arg;
5515 int cur_arg;
5516 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005517
5518 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005519 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5520 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5521 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5522 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5523 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005524
Willy Tarreau5581c272015-05-13 12:24:53 +02005525 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5526 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5527 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5528 file, linenum);
5529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005531 }
5532
5533 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005534 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005535 tcpcheck->action = TCPCHK_ACT_CONNECT;
5536
5537 /* parsing each parameters to fill up the rule */
5538 while (*(ptr_arg = args[cur_arg])) {
5539 /* tcp port */
5540 if (strcmp(args[cur_arg], "port") == 0) {
5541 if ( (atol(args[cur_arg + 1]) > 65535) ||
5542 (atol(args[cur_arg + 1]) < 1) ){
5543 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5544 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 }
5548 tcpcheck->port = atol(args[cur_arg + 1]);
5549 cur_arg += 2;
5550 }
5551 /* send proxy protocol */
5552 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5553 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5554 cur_arg++;
5555 }
5556#ifdef USE_OPENSSL
5557 else if (strcmp(args[cur_arg], "ssl") == 0) {
5558 curproxy->options |= PR_O_TCPCHK_SSL;
5559 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5560 cur_arg++;
5561 }
5562#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005563 /* comment for this tcpcheck line */
5564 else if (strcmp(args[cur_arg], "comment") == 0) {
5565 if (!*args[cur_arg + 1]) {
5566 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5567 file, linenum, args[cur_arg]);
5568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
5570 }
5571 tcpcheck->comment = strdup(args[cur_arg + 1]);
5572 cur_arg += 2;
5573 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005574 else {
5575#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005576 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 +01005577#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005578 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 +01005579#endif /* USE_OPENSSL */
5580 file, linenum, args[0], args[1], args[cur_arg]);
5581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
5583 }
5584
5585 }
5586
5587 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5588 }
5589 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005590 if (! *(args[2]) ) {
5591 /* SEND string expected */
5592 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5593 file, linenum, args[0], args[1], args[2]);
5594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
5596 } else {
5597 struct tcpcheck_rule *tcpcheck;
5598
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005599 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005600
5601 tcpcheck->action = TCPCHK_ACT_SEND;
5602 tcpcheck->string_len = strlen(args[2]);
5603 tcpcheck->string = strdup(args[2]);
5604 tcpcheck->expect_regex = NULL;
5605
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005606 /* comment for this tcpcheck line */
5607 if (strcmp(args[3], "comment") == 0) {
5608 if (!*args[4]) {
5609 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5610 file, linenum, args[3]);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
5614 tcpcheck->comment = strdup(args[4]);
5615 }
5616
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005617 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5618 }
5619 }
5620 else if (strcmp(args[1], "send-binary") == 0) {
5621 if (! *(args[2]) ) {
5622 /* SEND binary string expected */
5623 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5624 file, linenum, args[0], args[1], args[2]);
5625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 } else {
5628 struct tcpcheck_rule *tcpcheck;
5629 char *err = NULL;
5630
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005631 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005632
5633 tcpcheck->action = TCPCHK_ACT_SEND;
5634 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5635 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5636 file, linenum, args[0], args[1], args[2], err);
5637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
5639 }
5640 tcpcheck->expect_regex = NULL;
5641
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005642 /* comment for this tcpcheck line */
5643 if (strcmp(args[3], "comment") == 0) {
5644 if (!*args[4]) {
5645 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5646 file, linenum, args[3]);
5647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
5650 tcpcheck->comment = strdup(args[4]);
5651 }
5652
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005653 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5654 }
5655 }
5656 else if (strcmp(args[1], "expect") == 0) {
5657 const char *ptr_arg;
5658 int cur_arg;
5659 int inverse = 0;
5660
5661 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5662 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
5665 }
5666
5667 cur_arg = 2;
5668 /* consider exclamation marks, sole or at the beginning of a word */
5669 while (*(ptr_arg = args[cur_arg])) {
5670 while (*ptr_arg == '!') {
5671 inverse = !inverse;
5672 ptr_arg++;
5673 }
5674 if (*ptr_arg)
5675 break;
5676 cur_arg++;
5677 }
5678 /* now ptr_arg points to the beginning of a word past any possible
5679 * exclamation mark, and cur_arg is the argument which holds this word.
5680 */
5681 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005682 struct tcpcheck_rule *tcpcheck;
5683 char *err = NULL;
5684
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005685 if (!*(args[cur_arg + 1])) {
5686 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5687 file, linenum, args[0], args[1], ptr_arg);
5688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005691
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005692 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005693
5694 tcpcheck->action = TCPCHK_ACT_EXPECT;
5695 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5696 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5697 file, linenum, args[0], args[1], args[2], err);
5698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
5701 tcpcheck->expect_regex = NULL;
5702 tcpcheck->inverse = inverse;
5703
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005704 /* tcpcheck comment */
5705 cur_arg += 2;
5706 if (strcmp(args[cur_arg], "comment") == 0) {
5707 if (!*args[cur_arg + 1]) {
5708 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5709 file, linenum, args[cur_arg + 1]);
5710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
5712 }
5713 tcpcheck->comment = strdup(args[cur_arg + 1]);
5714 }
5715
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005716 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5717 }
5718 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005719 struct tcpcheck_rule *tcpcheck;
5720
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005721 if (!*(args[cur_arg + 1])) {
5722 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5723 file, linenum, args[0], args[1], ptr_arg);
5724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
5726 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005727
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005728 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005729
5730 tcpcheck->action = TCPCHK_ACT_EXPECT;
5731 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5732 tcpcheck->string = strdup(args[cur_arg + 1]);
5733 tcpcheck->expect_regex = NULL;
5734 tcpcheck->inverse = inverse;
5735
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005736 /* tcpcheck comment */
5737 cur_arg += 2;
5738 if (strcmp(args[cur_arg], "comment") == 0) {
5739 if (!*args[cur_arg + 1]) {
5740 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5741 file, linenum, args[cur_arg + 1]);
5742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
5744 }
5745 tcpcheck->comment = strdup(args[cur_arg + 1]);
5746 }
5747
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005748 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5749 }
5750 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005751 struct tcpcheck_rule *tcpcheck;
5752
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005753 if (!*(args[cur_arg + 1])) {
5754 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5755 file, linenum, args[0], args[1], ptr_arg);
5756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
5758 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005759
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005760 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005761
5762 tcpcheck->action = TCPCHK_ACT_EXPECT;
5763 tcpcheck->string_len = 0;
5764 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005765 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5766 error = NULL;
5767 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5768 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5769 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5770 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
5773 }
5774 tcpcheck->inverse = inverse;
5775
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005776 /* tcpcheck comment */
5777 cur_arg += 2;
5778 if (strcmp(args[cur_arg], "comment") == 0) {
5779 if (!*args[cur_arg + 1]) {
5780 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5781 file, linenum, args[cur_arg + 1]);
5782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
5784 }
5785 tcpcheck->comment = strdup(args[cur_arg + 1]);
5786 }
5787
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005788 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5789 }
5790 else {
5791 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5792 file, linenum, args[0], args[1], ptr_arg);
5793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
5795 }
5796 }
5797 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005798 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
5801 }
5802 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005803 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005804 if (curproxy == &defproxy) {
5805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005806 err_code |= ERR_ALERT | ERR_FATAL;
5807 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005808 }
5809
Willy Tarreaub80c2302007-11-30 20:51:32 +01005810 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005811 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005812
5813 if (strcmp(args[1], "fail") == 0) {
5814 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005815 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005816 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5817 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005818 err_code |= ERR_ALERT | ERR_FATAL;
5819 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005820 }
5821
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005822 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005823 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5824 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005825 err_code |= ERR_ALERT | ERR_FATAL;
5826 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005827 }
5828 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5829 }
5830 else {
5831 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005832 err_code |= ERR_ALERT | ERR_FATAL;
5833 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005834 }
5835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836#ifdef TPROXY
5837 else if (!strcmp(args[0], "transparent")) {
5838 /* enable transparent proxy connections */
5839 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005840 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 }
5843#endif
5844 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005845 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005847
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 if (*(args[1]) == 0) {
5849 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 }
5853 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005854 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005857 else if (!strcmp(args[0], "backlog")) { /* backlog */
5858 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005859 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005860
5861 if (*(args[1]) == 0) {
5862 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005863 err_code |= ERR_ALERT | ERR_FATAL;
5864 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005865 }
5866 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5868 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005869 }
Willy Tarreau86034312006-12-29 00:10:33 +01005870 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005872 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005873
Willy Tarreau86034312006-12-29 00:10:33 +01005874 if (*(args[1]) == 0) {
5875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005878 }
5879 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005880 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5881 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5884 if (*(args[1]) == 0) {
5885 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005886 err_code |= ERR_ALERT | ERR_FATAL;
5887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005889 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5890 if (err) {
5891 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5892 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005895 }
5896 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 }
5900 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005901 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005902 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005903 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005904
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 if (curproxy == &defproxy) {
5906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005907 err_code |= ERR_ALERT | ERR_FATAL;
5908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005909 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005910 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005911 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005912
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005913 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005914 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005915 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005916 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005917 goto out;
5918 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005919
5920 proto = protocol_by_family(sk->ss_family);
5921 if (!proto || !proto->connect) {
5922 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5923 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005924 err_code |= ERR_ALERT | ERR_FATAL;
5925 goto out;
5926 }
5927
5928 if (port1 != port2) {
5929 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5930 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005931 err_code |= ERR_ALERT | ERR_FATAL;
5932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005934
5935 if (!port1) {
5936 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5937 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
5940 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005941
William Lallemanddf1425a2015-04-28 20:17:49 +02005942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5943 goto out;
5944
Willy Tarreaud5191e72010-02-09 20:50:45 +01005945 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005946 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 }
5948 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005949 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005950 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005951
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005952 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5953 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005958 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005959 /**
5960 * The syntax for hash-type config element is
5961 * hash-type {map-based|consistent} [[<algo>] avalanche]
5962 *
5963 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5964 */
5965 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005966
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5968 err_code |= ERR_WARN;
5969
5970 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005971 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5972 }
5973 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005974 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5975 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005976 else if (strcmp(args[1], "avalanche") == 0) {
5977 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]);
5978 err_code |= ERR_ALERT | ERR_FATAL;
5979 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005980 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005981 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005982 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005983 err_code |= ERR_ALERT | ERR_FATAL;
5984 goto out;
5985 }
Bhaskar98634f02013-10-29 23:30:51 -04005986
5987 /* set the hash function to use */
5988 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005989 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005990 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005991
5992 /* if consistent with no argument, then avalanche modifier is also applied */
5993 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5994 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005995 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005996 /* set the hash function */
5997 if (!strcmp(args[2], "sdbm")) {
5998 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5999 }
6000 else if (!strcmp(args[2], "djb2")) {
6001 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01006002 }
6003 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01006004 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05006005 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01006006 else if (!strcmp(args[2], "crc32")) {
6007 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
6008 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05006009 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01006010 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 -05006011 err_code |= ERR_ALERT | ERR_FATAL;
6012 goto out;
6013 }
6014
6015 /* set the hash modifier */
6016 if (!strcmp(args[3], "avalanche")) {
6017 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
6018 }
6019 else if (*args[3]) {
6020 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
6021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
6023 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01006024 }
William Lallemanda73203e2012-03-12 12:48:57 +01006025 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04006026 else if (strcmp(args[0], "hash-balance-factor") == 0) {
6027 if (*(args[1]) == 0) {
6028 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
6029 err_code |= ERR_ALERT | ERR_FATAL;
6030 goto out;
6031 }
6032 curproxy->lbprm.chash.balance_factor = atol(args[1]);
6033 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
6034 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
6035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
6038 }
William Lallemanda73203e2012-03-12 12:48:57 +01006039 else if (strcmp(args[0], "unique-id-format") == 0) {
6040 if (!*(args[1])) {
6041 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044 }
William Lallemand3203ff42012-11-11 17:30:56 +01006045 if (*(args[2])) {
6046 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6047 err_code |= ERR_ALERT | ERR_FATAL;
6048 goto out;
6049 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006050 free(curproxy->conf.uniqueid_format_string);
6051 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006052
Willy Tarreau62a61232013-04-12 18:13:46 +02006053 free(curproxy->conf.uif_file);
6054 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6055 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006056 }
William Lallemanda73203e2012-03-12 12:48:57 +01006057
6058 else if (strcmp(args[0], "unique-id-header") == 0) {
6059 if (!*(args[1])) {
6060 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6061 err_code |= ERR_ALERT | ERR_FATAL;
6062 goto out;
6063 }
6064 free(curproxy->header_unique_id);
6065 curproxy->header_unique_id = strdup(args[1]);
6066 }
6067
William Lallemand723b73a2012-02-08 16:37:49 +01006068 else if (strcmp(args[0], "log-format") == 0) {
6069 if (!*(args[1])) {
6070 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6071 err_code |= ERR_ALERT | ERR_FATAL;
6072 goto out;
6073 }
William Lallemand3203ff42012-11-11 17:30:56 +01006074 if (*(args[2])) {
6075 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6076 err_code |= ERR_ALERT | ERR_FATAL;
6077 goto out;
6078 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006079 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
6080 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02006081
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006082 if (curproxy->conf.logformat_string == default_http_log_format)
6083 oldlogformat = "option httplog";
6084 else if (curproxy->conf.logformat_string == default_tcp_log_format)
6085 oldlogformat = "option tcplog";
6086 else if (curproxy->conf.logformat_string == clf_http_log_format)
6087 oldlogformat = "option httplog clf";
6088 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
6089 file, linenum, oldlogformat);
6090 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006091 if (curproxy->conf.logformat_string != default_http_log_format &&
6092 curproxy->conf.logformat_string != default_tcp_log_format &&
6093 curproxy->conf.logformat_string != clf_http_log_format)
6094 free(curproxy->conf.logformat_string);
6095 curproxy->conf.logformat_string = strdup(args[1]);
6096
6097 free(curproxy->conf.lfs_file);
6098 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6099 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006100
6101 /* get a chance to improve log-format error reporting by
6102 * reporting the correct line-number when possible.
6103 */
6104 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6105 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6106 file, linenum, curproxy->id);
6107 err_code |= ERR_WARN;
6108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006109 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006110 else if (!strcmp(args[0], "log-format-sd")) {
6111 if (!*(args[1])) {
6112 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6113 err_code |= ERR_ALERT | ERR_FATAL;
6114 goto out;
6115 }
6116 if (*(args[2])) {
6117 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6118 err_code |= ERR_ALERT | ERR_FATAL;
6119 goto out;
6120 }
6121
6122 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6123 free(curproxy->conf.logformat_sd_string);
6124 curproxy->conf.logformat_sd_string = strdup(args[1]);
6125
6126 free(curproxy->conf.lfsd_file);
6127 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6128 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6129
6130 /* get a chance to improve log-format-sd error reporting by
6131 * reporting the correct line-number when possible.
6132 */
6133 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6134 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6135 file, linenum, curproxy->id);
6136 err_code |= ERR_WARN;
6137 }
6138 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006139 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6140 if (*(args[1]) == 0) {
6141 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6142 err_code |= ERR_ALERT | ERR_FATAL;
6143 goto out;
6144 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006145 chunk_destroy(&curproxy->log_tag);
6146 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006147 }
William Lallemand0f99e342011-10-12 17:50:54 +02006148 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6149 /* delete previous herited or defined syslog servers */
6150 struct logsrv *back;
6151
6152 if (*(args[1]) != 0) {
6153 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
6156 }
6157
William Lallemand723b73a2012-02-08 16:37:49 +01006158 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6159 LIST_DEL(&tmplogsrv->list);
6160 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006161 }
6162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006163 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006164 struct logsrv *logsrv;
6165
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006167 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006168 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006169 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006170 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006171 LIST_INIT(&node->list);
6172 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174 }
6175 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006176 struct sockaddr_storage *sk;
6177 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006178 int arg = 0;
6179 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006180
Vincent Bernat02779b62016-04-03 13:48:43 +02006181 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182
Willy Tarreau18324f52014-06-27 18:10:07 +02006183 /* just after the address, a length may be specified */
6184 if (strcmp(args[arg+2], "len") == 0) {
6185 len = atoi(args[arg+3]);
6186 if (len < 80 || len > 65535) {
6187 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6188 file, linenum, args[arg+3]);
6189 err_code |= ERR_ALERT | ERR_FATAL;
6190 goto out;
6191 }
6192 logsrv->maxlen = len;
6193
6194 /* skip these two args */
6195 arg += 2;
6196 }
6197 else
6198 logsrv->maxlen = MAX_SYSLOG_LEN;
6199
Christopher Faulet084aa962017-08-29 16:54:41 +02006200 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006201 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006202
Dragan Dosen1322d092015-09-22 16:05:32 +02006203 /* after the length, a format may be specified */
6204 if (strcmp(args[arg+2], "format") == 0) {
6205 logsrv->format = get_log_format(args[arg+3]);
6206 if (logsrv->format < 0) {
6207 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6208 err_code |= ERR_ALERT | ERR_FATAL;
6209 goto out;
6210 }
6211
6212 /* skip these two args */
6213 arg += 2;
6214 }
6215
William Lallemanddf1425a2015-04-28 20:17:49 +02006216 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6217 goto out;
6218
Willy Tarreau18324f52014-06-27 18:10:07 +02006219 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006220 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006221 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006222 err_code |= ERR_ALERT | ERR_FATAL;
6223 goto out;
6224
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225 }
6226
William Lallemand0f99e342011-10-12 17:50:54 +02006227 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006228 if (*(args[arg+3])) {
6229 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006230 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006231 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234
Willy Tarreaubaaee002006-06-26 02:48:02 +02006235 }
6236 }
6237
William Lallemand0f99e342011-10-12 17:50:54 +02006238 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006239 if (*(args[arg+4])) {
6240 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006241 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006242 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006243 err_code |= ERR_ALERT | ERR_FATAL;
6244 goto out;
6245
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006246 }
6247 }
6248
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006249 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006250 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006251 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006252 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006253 goto out;
6254 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006255
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006256 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006257
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006258 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006259 if (port1 != port2) {
6260 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6261 file, linenum, args[0], args[1]);
6262 err_code |= ERR_ALERT | ERR_FATAL;
6263 goto out;
6264 }
6265
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006266 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006267 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006268 }
William Lallemand0f99e342011-10-12 17:50:54 +02006269
6270 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 }
6272 else {
6273 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006275 err_code |= ERR_ALERT | ERR_FATAL;
6276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 }
6278 }
6279 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006280 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006281 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006282 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006283 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006284
Willy Tarreau977b8e42006-12-29 14:19:17 +01006285 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006286 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006287
Willy Tarreaubaaee002006-06-26 02:48:02 +02006288 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006289 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6290 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006291 err_code |= ERR_ALERT | ERR_FATAL;
6292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006294
6295 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006296 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6297 free(curproxy->conn_src.iface_name);
6298 curproxy->conn_src.iface_name = NULL;
6299 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006300
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006301 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006302 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006303 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006304 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006305 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006306 goto out;
6307 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006308
6309 proto = protocol_by_family(sk->ss_family);
6310 if (!proto || !proto->connect) {
6311 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006312 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006313 err_code |= ERR_ALERT | ERR_FATAL;
6314 goto out;
6315 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006316
6317 if (port1 != port2) {
6318 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6319 file, linenum, args[0], args[1]);
6320 err_code |= ERR_ALERT | ERR_FATAL;
6321 goto out;
6322 }
6323
Willy Tarreauef9a3602012-12-08 22:29:20 +01006324 curproxy->conn_src.source_addr = *sk;
6325 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006326
6327 cur_arg = 2;
6328 while (*(args[cur_arg])) {
6329 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006330#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006331 if (!*args[cur_arg + 1]) {
6332 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6333 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006334 err_code |= ERR_ALERT | ERR_FATAL;
6335 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006336 }
6337
6338 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006339 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6340 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006341 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006342 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6343 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006344 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6345 char *name, *end;
6346
6347 name = args[cur_arg+1] + 7;
6348 while (isspace(*name))
6349 name++;
6350
6351 end = name;
6352 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6353 end++;
6354
Willy Tarreauef9a3602012-12-08 22:29:20 +01006355 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6356 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6357 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6358 curproxy->conn_src.bind_hdr_len = end - name;
6359 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6360 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6361 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006362
6363 /* now look for an occurrence number */
6364 while (isspace(*end))
6365 end++;
6366 if (*end == ',') {
6367 end++;
6368 name = end;
6369 if (*end == '-')
6370 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006371 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006372 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006373 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006374 }
6375
Willy Tarreauef9a3602012-12-08 22:29:20 +01006376 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006377 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6378 " occurrences values smaller than %d.\n",
6379 file, linenum, MAX_HDR_HISTORY);
6380 err_code |= ERR_ALERT | ERR_FATAL;
6381 goto out;
6382 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006383 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006384 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006385
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006386 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006387 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006388 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006389 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006390 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006391 goto out;
6392 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006393
6394 proto = protocol_by_family(sk->ss_family);
6395 if (!proto || !proto->connect) {
6396 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6397 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006398 err_code |= ERR_ALERT | ERR_FATAL;
6399 goto out;
6400 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006401
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006402 if (port1 != port2) {
6403 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6404 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006405 err_code |= ERR_ALERT | ERR_FATAL;
6406 goto out;
6407 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006408 curproxy->conn_src.tproxy_addr = *sk;
6409 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006410 }
6411 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006412#else /* no TPROXY support */
6413 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006414 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006415 err_code |= ERR_ALERT | ERR_FATAL;
6416 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006417#endif
6418 cur_arg += 2;
6419 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006420 }
6421
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006422 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6423#ifdef SO_BINDTODEVICE
6424 if (!*args[cur_arg + 1]) {
6425 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6426 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006427 err_code |= ERR_ALERT | ERR_FATAL;
6428 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006429 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006430 free(curproxy->conn_src.iface_name);
6431 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6432 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006433 global.last_checks |= LSTCHK_NETADM;
6434#else
6435 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6436 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006437 err_code |= ERR_ALERT | ERR_FATAL;
6438 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006439#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006440 cur_arg += 2;
6441 continue;
6442 }
6443 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006444 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006445 err_code |= ERR_ALERT | ERR_FATAL;
6446 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006449 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6450 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6451 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006452 err_code |= ERR_ALERT | ERR_FATAL;
6453 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006456 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006457 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006459 err_code |= ERR_ALERT | ERR_FATAL;
6460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462
6463 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006464 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006465 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006466 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006468 }
6469 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006470 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006471 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006472 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006473 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 }
6476 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006477 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006478 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006479 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006480 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 }
6483 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006484 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006485 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006486 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006487 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006489 }
6490 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
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_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006493 args[0], args[1], NULL, (const char **)args+2);
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006497 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this 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_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +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 Tarreaub8750a82006-09-03 09:56:00 +02006503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006505 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6507 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006508 err_code |= ERR_ALERT | ERR_FATAL;
6509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006510 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006511
6512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006513 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006514 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517 }
6518 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
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_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006521 args[0], args[1], NULL, (const char **)args+2);
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], "reqideny")) { /* deny a request if a header matches this 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_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +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], "reqipass")) { /* pass this header without allowing or denying the request */
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_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006540 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006541 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006542 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006543 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006546 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006547 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006548 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006549 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006550 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006551 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006554 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006555
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556 if (curproxy == &defproxy) {
6557 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006558 err_code |= ERR_ALERT | ERR_FATAL;
6559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006560 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006561 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006562 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006563
Willy Tarreaubaaee002006-06-26 02:48:02 +02006564 if (*(args[1]) == 0) {
6565 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006566 err_code |= ERR_ALERT | ERR_FATAL;
6567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006569
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006570 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006571 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006572 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6573 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006574 err_code |= ERR_ALERT | ERR_FATAL;
6575 goto out;
6576 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006577 err_code |= warnif_cond_conflicts(cond,
6578 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6579 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006580 }
6581 else if (*args[2]) {
6582 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6583 file, linenum, args[0], args[2]);
6584 err_code |= ERR_ALERT | ERR_FATAL;
6585 goto out;
6586 }
6587
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006588 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006589 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006590 wl->s = strdup(args[1]);
6591 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006592 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006593 }
6594 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006595 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006596 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006598 err_code |= ERR_ALERT | ERR_FATAL;
6599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006601
Willy Tarreauade5ec42010-01-28 19:33:49 +01006602 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006603 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006604 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006605 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006607 }
6608 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006609 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006610 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006611 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006612 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006614 }
6615 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006616 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006617 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006618 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006619 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006621 }
6622 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006623 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006624 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6625 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006626 err_code |= ERR_ALERT | ERR_FATAL;
6627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006628 }
6629
Willy Tarreauade5ec42010-01-28 19:33:49 +01006630 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006631 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006632 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006633 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006635 }
6636 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006637 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006638 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006639 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006640 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006642 }
6643 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006644 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006645 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006646 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006647 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006649 }
6650 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006651 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006652
Willy Tarreaubaaee002006-06-26 02:48:02 +02006653 if (curproxy == &defproxy) {
6654 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006655 err_code |= ERR_ALERT | ERR_FATAL;
6656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006657 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006658 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006659 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006660
Willy Tarreaubaaee002006-06-26 02:48:02 +02006661 if (*(args[1]) == 0) {
6662 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006663 err_code |= ERR_ALERT | ERR_FATAL;
6664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006665 }
6666
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006667 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006668 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006669 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6670 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006671 err_code |= ERR_ALERT | ERR_FATAL;
6672 goto out;
6673 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006674 err_code |= warnif_cond_conflicts(cond,
6675 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6676 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006677 }
6678 else if (*args[2]) {
6679 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6680 file, linenum, args[0], args[2]);
6681 err_code |= ERR_ALERT | ERR_FATAL;
6682 goto out;
6683 }
6684
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006685 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006686 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006687 wl->s = strdup(args[1]);
6688 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006689 }
6690 else if (!strcmp(args[0], "errorloc") ||
6691 !strcmp(args[0], "errorloc302") ||
6692 !strcmp(args[0], "errorloc303")) { /* error location */
6693 int errnum, errlen;
6694 char *err;
6695
Willy Tarreau977b8e42006-12-29 14:19:17 +01006696 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006697 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006698
Willy Tarreaubaaee002006-06-26 02:48:02 +02006699 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006700 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006701 err_code |= ERR_ALERT | ERR_FATAL;
6702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006703 }
6704
6705 errnum = atol(args[1]);
6706 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006707 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6708 err = malloc(errlen);
6709 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006711 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6712 err = malloc(errlen);
6713 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006714 }
6715
Willy Tarreau0f772532006-12-23 20:51:41 +01006716 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6717 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006718 chunk_destroy(&curproxy->errmsg[rc]);
6719 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006720 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006722 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006723
6724 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006725 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6726 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006727 free(err);
6728 }
6729 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006730 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6731 int errnum, errlen, fd;
6732 char *err;
6733 struct stat stat;
6734
6735 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006736 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006737
6738 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006739 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006740 err_code |= ERR_ALERT | ERR_FATAL;
6741 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006742 }
6743
6744 fd = open(args[2], O_RDONLY);
6745 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6746 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6747 file, linenum, args[2], args[1]);
6748 if (fd >= 0)
6749 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006750 err_code |= ERR_ALERT | ERR_FATAL;
6751 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006752 }
6753
Willy Tarreau27a674e2009-08-17 07:23:33 +02006754 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006755 errlen = stat.st_size;
6756 } else {
6757 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006758 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006759 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006760 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006761 }
6762
6763 err = malloc(errlen); /* malloc() must succeed during parsing */
6764 errnum = read(fd, err, errlen);
6765 if (errnum != errlen) {
6766 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6767 file, linenum, args[2], args[1]);
6768 close(fd);
6769 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006770 err_code |= ERR_ALERT | ERR_FATAL;
6771 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006772 }
6773 close(fd);
6774
6775 errnum = atol(args[1]);
6776 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6777 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006778 chunk_destroy(&curproxy->errmsg[rc]);
6779 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006780 break;
6781 }
6782 }
6783
6784 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006785 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6786 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006787 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006788 free(err);
6789 }
6790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006791 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006792 struct cfg_kw_list *kwl;
6793 int index;
6794
6795 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6796 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6797 if (kwl->kw[index].section != CFG_LISTEN)
6798 continue;
6799 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6800 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006801 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006802 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006803 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006804 err_code |= ERR_ALERT | ERR_FATAL;
6805 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006806 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006807 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006808 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006809 err_code |= ERR_WARN;
6810 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006811 }
Willy Tarreau93893792009-07-23 13:19:11 +02006812 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006813 }
6814 }
6815 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006816
Willy Tarreau6daf3432008-01-22 16:44:08 +01006817 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006818 err_code |= ERR_ALERT | ERR_FATAL;
6819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006820 }
Willy Tarreau93893792009-07-23 13:19:11 +02006821 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006822 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006823 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006824}
6825
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006826int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006827cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6828{
6829#ifdef CONFIG_HAP_NS
6830 const char *err;
6831 const char *item = args[0];
6832
6833 if (!strcmp(item, "namespace_list")) {
6834 return 0;
6835 }
6836 else if (!strcmp(item, "namespace")) {
6837 size_t idx = 1;
6838 const char *current;
6839 while (*(current = args[idx++])) {
6840 err = invalid_char(current);
6841 if (err) {
6842 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6843 file, linenum, *err, item, current);
6844 return ERR_ALERT | ERR_FATAL;
6845 }
6846
6847 if (netns_store_lookup(current, strlen(current))) {
6848 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6849 file, linenum, current);
6850 return ERR_ALERT | ERR_FATAL;
6851 }
6852 if (!netns_store_insert(current)) {
6853 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6854 file, linenum, current);
6855 return ERR_ALERT | ERR_FATAL;
6856 }
6857 }
6858 }
6859
6860 return 0;
6861#else
6862 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6863 file, linenum);
6864 return ERR_ALERT | ERR_FATAL;
6865#endif
6866}
6867
6868int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006869cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6870{
6871
6872 int err_code = 0;
6873 const char *err;
6874
6875 if (!strcmp(args[0], "userlist")) { /* new userlist */
6876 struct userlist *newul;
6877
6878 if (!*args[1]) {
6879 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6880 file, linenum, args[0]);
6881 err_code |= ERR_ALERT | ERR_FATAL;
6882 goto out;
6883 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006884 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6885 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006886
6887 err = invalid_char(args[1]);
6888 if (err) {
6889 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6890 file, linenum, *err, args[0], args[1]);
6891 err_code |= ERR_ALERT | ERR_FATAL;
6892 goto out;
6893 }
6894
6895 for (newul = userlist; newul; newul = newul->next)
6896 if (!strcmp(newul->name, args[1])) {
6897 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6898 file, linenum, args[1]);
6899 err_code |= ERR_WARN;
6900 goto out;
6901 }
6902
Vincent Bernat02779b62016-04-03 13:48:43 +02006903 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006904 if (!newul) {
6905 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6906 err_code |= ERR_ALERT | ERR_ABORT;
6907 goto out;
6908 }
6909
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006910 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006911 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006912 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6913 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006914 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006915 goto out;
6916 }
6917
6918 newul->next = userlist;
6919 userlist = newul;
6920
6921 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006922 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006923 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006924 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006925
6926 if (!*args[1]) {
6927 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6928 file, linenum, args[0]);
6929 err_code |= ERR_ALERT | ERR_FATAL;
6930 goto out;
6931 }
6932
6933 err = invalid_char(args[1]);
6934 if (err) {
6935 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6936 file, linenum, *err, args[0], args[1]);
6937 err_code |= ERR_ALERT | ERR_FATAL;
6938 goto out;
6939 }
6940
William Lallemand4ac9f542015-05-28 18:03:51 +02006941 if (!userlist)
6942 goto out;
6943
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006944 for (ag = userlist->groups; ag; ag = ag->next)
6945 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006946 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6947 file, linenum, args[1], userlist->name);
6948 err_code |= ERR_ALERT;
6949 goto out;
6950 }
6951
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006952 ag = calloc(1, sizeof(*ag));
6953 if (!ag) {
6954 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6955 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006956 goto out;
6957 }
6958
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006959 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006960 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006961 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6962 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006963 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006964 goto out;
6965 }
6966
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006967 cur_arg = 2;
6968
6969 while (*args[cur_arg]) {
6970 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006971 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006972 cur_arg += 2;
6973 continue;
6974 } else {
6975 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6976 file, linenum, args[0]);
6977 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006978 free(ag->groupusers);
6979 free(ag->name);
6980 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006981 goto out;
6982 }
6983 }
6984
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006985 ag->next = userlist->groups;
6986 userlist->groups = ag;
6987
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006988 } else if (!strcmp(args[0], "user")) { /* new user */
6989 struct auth_users *newuser;
6990 int cur_arg;
6991
6992 if (!*args[1]) {
6993 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6994 file, linenum, args[0]);
6995 err_code |= ERR_ALERT | ERR_FATAL;
6996 goto out;
6997 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006998 if (!userlist)
6999 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007000
7001 for (newuser = userlist->users; newuser; newuser = newuser->next)
7002 if (!strcmp(newuser->user, args[1])) {
7003 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
7004 file, linenum, args[1], userlist->name);
7005 err_code |= ERR_ALERT;
7006 goto out;
7007 }
7008
Vincent Bernat02779b62016-04-03 13:48:43 +02007009 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007010 if (!newuser) {
7011 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
7012 err_code |= ERR_ALERT | ERR_ABORT;
7013 goto out;
7014 }
7015
7016 newuser->user = strdup(args[1]);
7017
7018 newuser->next = userlist->users;
7019 userlist->users = newuser;
7020
7021 cur_arg = 2;
7022
7023 while (*args[cur_arg]) {
7024 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02007025#ifdef CONFIG_HAP_CRYPT
7026 if (!crypt("", args[cur_arg + 1])) {
7027 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
7028 file, linenum, newuser->user);
7029 err_code |= ERR_ALERT | ERR_FATAL;
7030 goto out;
7031 }
7032#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007033 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
7034 file, linenum);
7035 err_code |= ERR_ALERT;
7036#endif
7037 newuser->pass = strdup(args[cur_arg + 1]);
7038 cur_arg += 2;
7039 continue;
7040 } else if (!strcmp(args[cur_arg], "insecure-password")) {
7041 newuser->pass = strdup(args[cur_arg + 1]);
7042 newuser->flags |= AU_O_INSECURE;
7043 cur_arg += 2;
7044 continue;
7045 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007046 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007047 cur_arg += 2;
7048 continue;
7049 } else {
7050 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7051 file, linenum, args[0]);
7052 err_code |= ERR_ALERT | ERR_FATAL;
7053 goto out;
7054 }
7055 }
7056 } else {
7057 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7058 err_code |= ERR_ALERT | ERR_FATAL;
7059 }
7060
7061out:
7062 return err_code;
7063}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007064
Christopher Faulet79bdef32016-11-04 22:36:15 +01007065int
7066cfg_parse_scope(const char *file, int linenum, char *line)
7067{
7068 char *beg, *end, *scope = NULL;
7069 int err_code = 0;
7070 const char *err;
7071
7072 beg = line + 1;
7073 end = strchr(beg, ']');
7074
7075 /* Detect end of scope declaration */
7076 if (!end || end == beg) {
7077 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7078 file, linenum);
7079 err_code |= ERR_ALERT | ERR_FATAL;
7080 goto out;
7081 }
7082
7083 /* Get scope name and check its validity */
7084 scope = my_strndup(beg, end-beg);
7085 err = invalid_char(scope);
7086 if (err) {
7087 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7088 file, linenum, *err);
7089 err_code |= ERR_ALERT | ERR_ABORT;
7090 goto out;
7091 }
7092
7093 /* Be sure to have a scope declaration alone on its line */
7094 line = end+1;
7095 while (isspace((unsigned char)*line))
7096 line++;
7097 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7098 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7099 file, linenum, *line);
7100 err_code |= ERR_ALERT | ERR_ABORT;
7101 goto out;
7102 }
7103
7104 /* We have a valid scope declaration, save it */
7105 free(cfg_scope);
7106 cfg_scope = scope;
7107 scope = NULL;
7108
7109 out:
7110 free(scope);
7111 return err_code;
7112}
7113
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114/*
7115 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007116 * Returns the error code, 0 if OK, or any combination of :
7117 * - ERR_ABORT: must abort ASAP
7118 * - ERR_FATAL: we can continue parsing but not start the service
7119 * - ERR_WARN: a warning has been emitted
7120 * - ERR_ALERT: an alert has been emitted
7121 * Only the two first ones can stop processing, the two others are just
7122 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007124int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007125{
William Lallemand64e84512015-05-12 14:25:37 +02007126 char *thisline;
7127 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007128 FILE *f;
7129 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007130 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007131 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007132 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007133 int readbytes = 0;
7134
7135 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007136 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007137 return -1;
7138 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007139
David Carlier97880bb2016-04-08 10:35:26 +01007140 if ((f=fopen(file,"r")) == NULL) {
7141 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007142 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007144
William Lallemandb2f07452015-05-12 14:27:13 +02007145next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007146 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007147 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007148 char *end;
7149 char *args[MAX_LINE_ARGS + 1];
7150 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007151 int dquote = 0; /* double quote */
7152 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007153
Willy Tarreaubaaee002006-06-26 02:48:02 +02007154 linenum++;
7155
7156 end = line + strlen(line);
7157
William Lallemand64e84512015-05-12 14:25:37 +02007158 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007159 /* Check if we reached the limit and the last char is not \n.
7160 * Watch out for the last line without the terminating '\n'!
7161 */
William Lallemand64e84512015-05-12 14:25:37 +02007162 char *newline;
7163 int newlinesize = linesize * 2;
7164
7165 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7166 if (newline == NULL) {
7167 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7168 file, linenum);
7169 err_code |= ERR_ALERT | ERR_FATAL;
7170 continue;
7171 }
7172
7173 readbytes = linesize - 1;
7174 linesize = newlinesize;
7175 thisline = newline;
7176 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007177 }
7178
William Lallemand64e84512015-05-12 14:25:37 +02007179 readbytes = 0;
7180
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007182 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007183 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007184
Christopher Faulet79bdef32016-11-04 22:36:15 +01007185
7186 if (*line == '[') {/* This is the begining if a scope */
7187 err_code |= cfg_parse_scope(file, linenum, line);
7188 goto next_line;
7189 }
7190
Willy Tarreaubaaee002006-06-26 02:48:02 +02007191 arg = 0;
7192 args[arg] = line;
7193
7194 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007195 if (*line == '"' && !squote) { /* double quote outside single quotes */
7196 if (dquote)
7197 dquote = 0;
7198 else
7199 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007200 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007201 end--;
7202 }
7203 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7204 if (squote)
7205 squote = 0;
7206 else
7207 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007208 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007209 end--;
7210 }
7211 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007212 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7213 * C equivalent value. Other combinations left unchanged (eg: \1).
7214 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007215 int skip = 0;
7216 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7217 *line = line[1];
7218 skip = 1;
7219 }
7220 else if (line[1] == 'r') {
7221 *line = '\r';
7222 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007224 else if (line[1] == 'n') {
7225 *line = '\n';
7226 skip = 1;
7227 }
7228 else if (line[1] == 't') {
7229 *line = '\t';
7230 skip = 1;
7231 }
7232 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007233 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007234 unsigned char hex1, hex2;
7235 hex1 = toupper(line[2]) - '0';
7236 hex2 = toupper(line[3]) - '0';
7237 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7238 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7239 *line = (hex1<<4) + hex2;
7240 skip = 3;
7241 }
7242 else {
7243 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007244 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007245 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007246 } else if (line[1] == '"') {
7247 *line = '"';
7248 skip = 1;
7249 } else if (line[1] == '\'') {
7250 *line = '\'';
7251 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007252 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7253 *line = '$';
7254 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007255 }
7256 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007257 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007258 end -= skip;
7259 }
7260 line++;
7261 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007262 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007263 /* end of string, end of loop */
7264 *line = 0;
7265 break;
7266 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007267 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007268 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007269 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007270 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007271 line++;
7272 args[++arg] = line;
7273 }
William Lallemandb2f07452015-05-12 14:27:13 +02007274 else if (dquote && *line == '$') {
7275 /* environment variables are evaluated inside double quotes */
7276 char *var_beg;
7277 char *var_end;
7278 char save_char;
7279 char *value;
7280 int val_len;
7281 int newlinesize;
7282 int braces = 0;
7283
7284 var_beg = line + 1;
7285 var_end = var_beg;
7286
7287 if (*var_beg == '{') {
7288 var_beg++;
7289 var_end++;
7290 braces = 1;
7291 }
7292
7293 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7294 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7295 err_code |= ERR_ALERT | ERR_FATAL;
7296 goto next_line; /* skip current line */
7297 }
7298
7299 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7300 var_end++;
7301
7302 save_char = *var_end;
7303 *var_end = '\0';
7304 value = getenv(var_beg);
7305 *var_end = save_char;
7306 val_len = value ? strlen(value) : 0;
7307
7308 if (braces) {
7309 if (*var_end == '}') {
7310 var_end++;
7311 braces = 0;
7312 } else {
7313 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7314 err_code |= ERR_ALERT | ERR_FATAL;
7315 goto next_line; /* skip current line */
7316 }
7317 }
7318
7319 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7320
7321 /* if not enough space in thisline */
7322 if (newlinesize > linesize) {
7323 char *newline;
7324
7325 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7326 if (newline == NULL) {
7327 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7328 err_code |= ERR_ALERT | ERR_FATAL;
7329 goto next_line; /* slip current line */
7330 }
7331 /* recompute pointers if realloc returns a new pointer */
7332 if (newline != thisline) {
7333 int i;
7334 int diff;
7335
7336 for (i = 0; i <= arg; i++) {
7337 diff = args[i] - thisline;
7338 args[i] = newline + diff;
7339 }
7340
7341 diff = var_end - thisline;
7342 var_end = newline + diff;
7343 diff = end - thisline;
7344 end = newline + diff;
7345 diff = line - thisline;
7346 line = newline + diff;
7347 thisline = newline;
7348 }
7349 linesize = newlinesize;
7350 }
7351
7352 /* insert value inside the line */
7353 memmove(line + val_len, var_end, end - var_end + 1);
7354 memcpy(line, value, val_len);
7355 end += val_len - (var_end - line);
7356 line += val_len;
7357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007358 else {
7359 line++;
7360 }
7361 }
William Lallemandb2f07452015-05-12 14:27:13 +02007362
William Lallemandf9873ba2015-05-05 17:37:14 +02007363 if (dquote) {
7364 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7365 err_code |= ERR_ALERT | ERR_FATAL;
7366 }
7367
7368 if (squote) {
7369 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7370 err_code |= ERR_ALERT | ERR_FATAL;
7371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007372
7373 /* empty line */
7374 if (!**args)
7375 continue;
7376
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007377 if (*line) {
7378 /* we had to stop due to too many args.
7379 * Let's terminate the string, print the offending part then cut the
7380 * last arg.
7381 */
7382 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7383 line++;
7384 *line = '\0';
7385
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007386 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007387 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007388 err_code |= ERR_ALERT | ERR_FATAL;
7389 args[arg] = line;
7390 }
7391
Willy Tarreau540abe42007-05-02 20:50:16 +02007392 /* zero out remaining args and ensure that at least one entry
7393 * is zeroed out.
7394 */
7395 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007396 args[arg] = line;
7397 }
7398
Willy Tarreau3842f002009-06-14 11:39:52 +02007399 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007400 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007401 char *tmp;
7402
Willy Tarreau3842f002009-06-14 11:39:52 +02007403 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007404 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007405 for (arg=0; *args[arg+1]; arg++)
7406 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007407 *tmp = '\0'; // fix the next arg to \0
7408 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007409 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007410 else if (!strcmp(args[0], "default")) {
7411 kwm = KWM_DEF;
7412 for (arg=0; *args[arg+1]; arg++)
7413 args[arg] = args[arg+1]; // shift args after inversion
7414 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007415
William Lallemand0f99e342011-10-12 17:50:54 +02007416 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7417 strcmp(args[0], "log") != 0) {
7418 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007419 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007420 }
7421
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007422 /* detect section start */
7423 list_for_each_entry(ics, &sections, list) {
7424 if (strcmp(args[0], ics->section_name) == 0) {
7425 cursection = ics->section_name;
7426 cs = ics;
7427 break;
7428 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007429 }
7430
William Lallemandd2ff56d2017-10-16 11:06:50 +02007431 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007432 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007433 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007434 } else {
7435 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007436
William Lallemandd2ff56d2017-10-16 11:06:50 +02007437 if (pcs != cs && pcs && pcs->post_section_parser) {
7438 err_code |= pcs->post_section_parser();
7439 if (err_code & ERR_ABORT)
7440 goto err;
7441 }
7442
7443 err_code |= cs->section_parser(file, linenum, args, kwm);
7444 if (err_code & ERR_ABORT)
7445 goto err;
7446 }
7447 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007448 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007449
7450 if (pcs == cs && pcs && pcs->post_section_parser)
7451 err_code |= pcs->post_section_parser();
7452
7453err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007454 free(cfg_scope);
7455 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007456 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007457 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007458 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007459 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007460}
7461
Willy Tarreau64ab6072014-09-16 12:17:36 +02007462/* This function propagates processes from frontend <from> to backend <to> so
7463 * that it is always guaranteed that a backend pointed to by a frontend is
7464 * bound to all of its processes. After that, if the target is a "listen"
7465 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007466 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007467 * checked first to ensure that <to> is already bound to all processes of
7468 * <from>, there is no risk of looping and we ensure to follow the shortest
7469 * path to the destination.
7470 *
7471 * It is possible to set <to> to NULL for the first call so that the function
7472 * takes care of visiting the initial frontend in <from>.
7473 *
7474 * It is important to note that the function relies on the fact that all names
7475 * have already been resolved.
7476 */
7477void propagate_processes(struct proxy *from, struct proxy *to)
7478{
7479 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007480
7481 if (to) {
7482 /* check whether we need to go down */
7483 if (from->bind_proc &&
7484 (from->bind_proc & to->bind_proc) == from->bind_proc)
7485 return;
7486
7487 if (!from->bind_proc && !to->bind_proc)
7488 return;
7489
7490 to->bind_proc = from->bind_proc ?
7491 (to->bind_proc | from->bind_proc) : 0;
7492
7493 /* now propagate down */
7494 from = to;
7495 }
7496
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007497 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007498 return;
7499
Willy Tarreauf6b70012014-12-18 14:00:43 +01007500 if (from->state == PR_STSTOPPED)
7501 return;
7502
Willy Tarreau64ab6072014-09-16 12:17:36 +02007503 /* default_backend */
7504 if (from->defbe.be)
7505 propagate_processes(from, from->defbe.be);
7506
7507 /* use_backend */
7508 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007509 if (rule->dynamic)
7510 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007511 to = rule->be.backend;
7512 propagate_processes(from, to);
7513 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007514}
7515
Willy Tarreaubb925012009-07-23 13:36:36 +02007516/*
7517 * Returns the error code, 0 if OK, or any combination of :
7518 * - ERR_ABORT: must abort ASAP
7519 * - ERR_FATAL: we can continue parsing but not start the service
7520 * - ERR_WARN: a warning has been emitted
7521 * - ERR_ALERT: an alert has been emitted
7522 * Only the two first ones can stop processing, the two others are just
7523 * indicators.
7524 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007525int check_config_validity()
7526{
7527 int cfgerr = 0;
7528 struct proxy *curproxy = NULL;
7529 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007530 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007531 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007532 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007533 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007534 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007535
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007536 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007537 /*
7538 * Now, check for the integrity of all that we have collected.
7539 */
7540
7541 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007542 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007543
Willy Tarreau193b8c62012-11-22 00:17:38 +01007544 if (!global.tune.max_http_hdr)
7545 global.tune.max_http_hdr = MAX_HTTP_HDR;
7546
7547 if (!global.tune.cookie_len)
7548 global.tune.cookie_len = CAPTURE_LEN;
7549
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007550 if (!global.tune.requri_len)
7551 global.tune.requri_len = REQURI_LEN;
7552
Emeric Brun96fd9262017-07-05 13:33:16 +02007553 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7554
Willy Tarreau193b8c62012-11-22 00:17:38 +01007555 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7556
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007557 /* Post initialisation of the users and groups lists. */
7558 err_code = userlist_postinit();
7559 if (err_code != ERR_NONE)
7560 goto out;
7561
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007562 /* first, we will invert the proxy list order */
7563 curproxy = NULL;
7564 while (proxy) {
7565 struct proxy *next;
7566
7567 next = proxy->next;
7568 proxy->next = curproxy;
7569 curproxy = proxy;
7570 if (!next)
7571 break;
7572 proxy = next;
7573 }
7574
Willy Tarreau419ead82014-09-16 13:41:21 +02007575 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007576 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007577 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007578 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007579 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007580 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007581 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007582 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007583
Willy Tarreau050536d2012-10-04 08:47:34 +02007584 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007585 /* proxy ID not set, use automatic numbering with first
7586 * spare entry starting with next_pxid.
7587 */
7588 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7589 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7590 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007591 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007592 next_pxid++;
7593
Willy Tarreau55ea7572007-06-17 19:56:27 +02007594
Willy Tarreaubaaee002006-06-26 02:48:02 +02007595 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007596 /* ensure we don't keep listeners uselessly bound */
7597 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007598 free((void *)curproxy->table.peers.name);
7599 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007600 continue;
7601 }
7602
Willy Tarreau102df612014-05-07 23:56:38 +02007603 /* Check multi-process mode compatibility for the current proxy */
7604
7605 if (curproxy->bind_proc) {
7606 /* an explicit bind-process was specified, let's check how many
7607 * processes remain.
7608 */
David Carliere6c39412015-07-02 07:00:17 +00007609 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007610
7611 curproxy->bind_proc &= nbits(global.nbproc);
7612 if (!curproxy->bind_proc && nbproc == 1) {
7613 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);
7614 curproxy->bind_proc = 1;
7615 }
7616 else if (!curproxy->bind_proc && nbproc > 1) {
7617 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);
7618 curproxy->bind_proc = 0;
7619 }
7620 }
7621
Willy Tarreau3d209582014-05-09 17:06:11 +02007622 /* check and reduce the bind-proc of each listener */
7623 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7624 unsigned long mask;
7625
Willy Tarreau45a66cc2017-11-24 11:28:00 +01007626 /* HTTP frontends with "h2" as ALPN/NPN will work in
7627 * HTTP/2 and absolutely require buffers 16kB or larger.
7628 */
7629#ifdef USE_OPENSSL
7630 if (curproxy->mode == PR_MODE_HTTP && global.tune.bufsize < 16384) {
7631#ifdef OPENSSL_NPN_NEGOTIATED
7632 /* check NPN */
7633 if (bind_conf->ssl_conf.npn_str && strcmp(bind_conf->ssl_conf.npn_str, "\002h2") == 0) {
7634 Alert("config : HTTP frontend '%s' enables HTTP/2 via NPN at [%s:%d], so global.tune.bufsize must be at least 16384 bytes (%d now).\n",
7635 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
7636 cfgerr++;
7637 }
7638#endif
7639#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7640 /* check ALPN */
7641 if (bind_conf->ssl_conf.alpn_str && strcmp(bind_conf->ssl_conf.alpn_str, "\002h2") == 0) {
7642 Alert("config : HTTP frontend '%s' enables HTTP/2 via ALPN at [%s:%d], so global.tune.bufsize must be at least 16384 bytes (%d now).\n",
7643 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
7644 cfgerr++;
7645 }
7646#endif
7647 } /* HTTP && bufsize < 16384 */
7648#endif
7649
Willy Tarreau3d209582014-05-09 17:06:11 +02007650 if (!bind_conf->bind_proc)
7651 continue;
7652
7653 mask = nbits(global.nbproc);
7654 if (curproxy->bind_proc)
7655 mask &= curproxy->bind_proc;
7656 /* mask cannot be null here thanks to the previous checks */
7657
David Carliere6c39412015-07-02 07:00:17 +00007658 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007659 bind_conf->bind_proc &= mask;
7660
7661 if (!bind_conf->bind_proc && nbproc == 1) {
7662 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",
7663 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7664 bind_conf->bind_proc = mask & ~(mask - 1);
7665 }
7666 else if (!bind_conf->bind_proc && nbproc > 1) {
7667 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",
7668 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7669 bind_conf->bind_proc = 0;
7670 }
7671 }
7672
Willy Tarreauff01a212009-03-15 13:46:16 +01007673 switch (curproxy->mode) {
7674 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007675 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007676 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007677 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7678 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007679 cfgerr++;
7680 }
7681
7682 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007683 Warning("config : servers will be ignored for %s '%s'.\n",
7684 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007685 break;
7686
7687 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007688 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007689 break;
7690
7691 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007692 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007693 break;
7694 }
7695
Willy Tarreauf3934b82015-08-11 11:36:45 +02007696 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7697 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7698 proxy_type_str(curproxy), curproxy->id);
7699 err_code |= ERR_WARN;
7700 }
7701
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007702 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007703 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007704 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007705 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7706 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007707 cfgerr++;
7708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007709#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007710 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007711 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7712 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007713 cfgerr++;
7714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007715#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007716 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007717 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7718 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007719 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007720 }
7721 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007722 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007723 /* If no LB algo is set in a backend, and we're not in
7724 * transparent mode, dispatch mode nor proxy mode, we
7725 * want to use balance roundrobin by default.
7726 */
7727 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7728 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007729 }
7730 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007731
Willy Tarreau1620ec32011-08-06 17:05:02 +02007732 if (curproxy->options & PR_O_DISPATCH)
7733 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7734 else if (curproxy->options & PR_O_HTTP_PROXY)
7735 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7736 else if (curproxy->options & PR_O_TRANSP)
7737 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007738
Willy Tarreau1620ec32011-08-06 17:05:02 +02007739 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7740 if (curproxy->options & PR_O_DISABLE404) {
7741 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7742 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7743 err_code |= ERR_WARN;
7744 curproxy->options &= ~PR_O_DISABLE404;
7745 }
7746 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7747 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7748 "send-state", proxy_type_str(curproxy), curproxy->id);
7749 err_code |= ERR_WARN;
7750 curproxy->options &= ~PR_O2_CHK_SNDST;
7751 }
Willy Tarreauef781042010-01-27 11:53:01 +01007752 }
7753
Simon Horman98637e52014-06-20 12:30:16 +09007754 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7755 if (!global.external_check) {
7756 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7757 curproxy->id, "option external-check");
7758 cfgerr++;
7759 }
7760 if (!curproxy->check_command) {
7761 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7762 curproxy->id, "option external-check");
7763 cfgerr++;
7764 }
7765 }
7766
Simon Horman64e34162015-02-06 11:11:57 +09007767 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007768 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7769 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007770 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7771 "'email-alert myhostname', or 'email-alert to' "
7772 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007773 "to be present).\n",
7774 proxy_type_str(curproxy), curproxy->id);
7775 err_code |= ERR_WARN;
7776 free_email_alert(curproxy);
7777 }
7778 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007779 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007780 }
7781
Simon Horman98637e52014-06-20 12:30:16 +09007782 if (curproxy->check_command) {
7783 int clear = 0;
7784 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7785 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7786 "external-check command", proxy_type_str(curproxy), curproxy->id);
7787 err_code |= ERR_WARN;
7788 clear = 1;
7789 }
7790 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007791 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007792 curproxy->id, "external-check command");
7793 cfgerr++;
7794 }
7795 if (clear) {
7796 free(curproxy->check_command);
7797 curproxy->check_command = NULL;
7798 }
7799 }
7800
7801 if (curproxy->check_path) {
7802 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7803 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7804 "external-check path", proxy_type_str(curproxy), curproxy->id);
7805 err_code |= ERR_WARN;
7806 free(curproxy->check_path);
7807 curproxy->check_path = NULL;
7808 }
7809 }
7810
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007811 /* if a default backend was specified, let's find it */
7812 if (curproxy->defbe.name) {
7813 struct proxy *target;
7814
Willy Tarreauafb39922015-05-26 12:04:09 +02007815 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007816 if (!target) {
7817 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7818 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007819 cfgerr++;
7820 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007821 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7822 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007823 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007824 } else if (target->mode != curproxy->mode &&
7825 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7826
7827 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7828 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7829 curproxy->conf.file, curproxy->conf.line,
7830 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7831 target->conf.file, target->conf.line);
7832 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007833 } else {
7834 free(curproxy->defbe.name);
7835 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007836 /* Update tot_fe_maxconn for a further fullconn's computation */
7837 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007838 /* Emit a warning if this proxy also has some servers */
7839 if (curproxy->srv) {
7840 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7841 curproxy->id);
7842 err_code |= ERR_WARN;
7843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007844 }
7845 }
7846
Emeric Brun3f783572017-01-12 11:21:28 +01007847 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7848 /* Case of listen without default backend
7849 * The curproxy will be its own default backend
7850 * so we update tot_fe_maxconn for a further
7851 * fullconn's computation */
7852 curproxy->tot_fe_maxconn += curproxy->maxconn;
7853 }
7854
Willy Tarreau55ea7572007-06-17 19:56:27 +02007855 /* find the target proxy for 'use_backend' rules */
7856 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007857 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007858 struct logformat_node *node;
7859 char *pxname;
7860
7861 /* Try to parse the string as a log format expression. If the result
7862 * of the parsing is only one entry containing a simple string, then
7863 * it's a standard string corresponding to a static rule, thus the
7864 * parsing is cancelled and be.name is restored to be resolved.
7865 */
7866 pxname = rule->be.name;
7867 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007868 curproxy->conf.args.ctx = ARGC_UBK;
7869 curproxy->conf.args.file = rule->file;
7870 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007871 err = NULL;
7872 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7873 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7874 rule->file, rule->line, pxname, err);
7875 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007876 cfgerr++;
7877 continue;
7878 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007879 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7880
7881 if (!LIST_ISEMPTY(&rule->be.expr)) {
7882 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7883 rule->dynamic = 1;
7884 free(pxname);
7885 continue;
7886 }
7887 /* simple string: free the expression and fall back to static rule */
7888 free(node->arg);
7889 free(node);
7890 }
7891
7892 rule->dynamic = 0;
7893 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007894
Willy Tarreauafb39922015-05-26 12:04:09 +02007895 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007896 if (!target) {
7897 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7898 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007899 cfgerr++;
7900 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007901 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7902 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007903 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007904 } else if (target->mode != curproxy->mode &&
7905 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7906
7907 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7908 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7909 curproxy->conf.file, curproxy->conf.line,
7910 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7911 target->conf.file, target->conf.line);
7912 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007913 } else {
7914 free((void *)rule->be.name);
7915 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007916 /* For each target of switching rules, we update
7917 * their tot_fe_maxconn, except if a previous rule point
7918 * on the same backend or on the default backend */
7919 if (rule->be.backend != curproxy->defbe.be) {
7920 struct switching_rule *swrule;
7921
7922 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7923 if (rule == swrule) {
7924 target->tot_fe_maxconn += curproxy->maxconn;
7925 break;
7926 }
7927 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7928 /* there is multiple ref of this backend */
7929 break;
7930 }
7931 }
7932 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007933 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007934 }
7935
Willy Tarreau64ab6072014-09-16 12:17:36 +02007936 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007937 list_for_each_entry(srule, &curproxy->server_rules, list) {
7938 struct server *target = findserver(curproxy, srule->srv.name);
7939
7940 if (!target) {
7941 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7942 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7943 cfgerr++;
7944 continue;
7945 }
7946 free((void *)srule->srv.name);
7947 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007948 }
7949
Emeric Brunb982a3d2010-01-04 15:45:53 +01007950 /* find the target table for 'stick' rules */
7951 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7952 struct proxy *target;
7953
Emeric Brun1d33b292010-01-04 15:47:17 +01007954 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7955 if (mrule->flags & STK_IS_STORE)
7956 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7957
Emeric Brunb982a3d2010-01-04 15:45:53 +01007958 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007959 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007960 else
7961 target = curproxy;
7962
7963 if (!target) {
7964 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7965 curproxy->id, mrule->table.name);
7966 cfgerr++;
7967 }
7968 else if (target->table.size == 0) {
7969 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7970 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7971 cfgerr++;
7972 }
Willy Tarreau12785782012-04-27 21:37:17 +02007973 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7974 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007975 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7976 cfgerr++;
7977 }
7978 else {
7979 free((void *)mrule->table.name);
7980 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007981 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007982 }
7983 }
7984
7985 /* find the target table for 'store response' rules */
7986 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7987 struct proxy *target;
7988
Emeric Brun1d33b292010-01-04 15:47:17 +01007989 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7990
Emeric Brunb982a3d2010-01-04 15:45:53 +01007991 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007992 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007993 else
7994 target = curproxy;
7995
7996 if (!target) {
7997 Alert("Proxy '%s': unable to find store table '%s'.\n",
7998 curproxy->id, mrule->table.name);
7999 cfgerr++;
8000 }
8001 else if (target->table.size == 0) {
8002 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
8003 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
8004 cfgerr++;
8005 }
Willy Tarreau12785782012-04-27 21:37:17 +02008006 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
8007 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01008008 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
8009 cfgerr++;
8010 }
8011 else {
8012 free((void *)mrule->table.name);
8013 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02008014 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01008015 }
8016 }
8017
Christopher Faulete4e830d2017-09-18 14:51:41 +02008018 /* check validity for 'tcp-request' layer 4 rules */
8019 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
8020 err = NULL;
8021 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8022 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8023 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01008024 cfgerr++;
8025 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008026 }
8027
Christopher Faulete4e830d2017-09-18 14:51:41 +02008028 /* check validity for 'tcp-request' layer 5 rules */
8029 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
8030 err = NULL;
8031 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8032 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8033 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01008034 cfgerr++;
8035 }
8036 }
8037
Christopher Faulete4e830d2017-09-18 14:51:41 +02008038 /* check validity for 'tcp-request' layer 6 rules */
8039 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8040 err = NULL;
8041 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8042 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8043 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01008044 cfgerr++;
8045 }
8046 }
8047
Christopher Faulete4e830d2017-09-18 14:51:41 +02008048 /* check validity for 'http-request' layer 7 rules */
8049 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
8050 err = NULL;
8051 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8052 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8053 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008054 cfgerr++;
8055 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008056 }
8057
Christopher Faulete4e830d2017-09-18 14:51:41 +02008058 /* check validity for 'http-response' layer 7 rules */
8059 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
8060 err = NULL;
8061 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8062 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8063 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02008064 cfgerr++;
8065 }
Willy Tarreau09448f72014-06-25 18:12:15 +02008066 }
8067
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008068 /* move any "block" rules at the beginning of the http-request rules */
8069 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8070 /* insert block_rules into http_req_rules at the beginning */
8071 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8072 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8073 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8074 curproxy->http_req_rules.n = curproxy->block_rules.n;
8075 LIST_INIT(&curproxy->block_rules);
8076 }
8077
Emeric Brun32da3c42010-09-23 18:39:19 +02008078 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008079 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008080
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008081 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008082 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8083 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008084 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008085 break;
8086 }
8087 }
8088
8089 if (!curpeers) {
8090 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8091 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008092 free((void *)curproxy->table.peers.name);
8093 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008094 cfgerr++;
8095 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008096 else if (curpeers->state == PR_STSTOPPED) {
8097 /* silently disable this peers section */
8098 curproxy->table.peers.p = NULL;
8099 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008100 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008101 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8102 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008103 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008104 cfgerr++;
8105 }
8106 }
8107
Simon Horman9dc49962015-01-30 11:22:59 +09008108
8109 if (curproxy->email_alert.mailers.name) {
8110 struct mailers *curmailers = mailers;
8111
8112 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02008113 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09008114 break;
Simon Horman9dc49962015-01-30 11:22:59 +09008115 }
Simon Horman9dc49962015-01-30 11:22:59 +09008116 if (!curmailers) {
8117 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8118 curproxy->id, curproxy->email_alert.mailers.name);
8119 free_email_alert(curproxy);
8120 cfgerr++;
8121 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02008122 else {
8123 err = NULL;
8124 if (init_email_alert(curmailers, curproxy, &err)) {
8125 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8126 free(err);
8127 cfgerr++;
8128 }
8129 }
Simon Horman9dc49962015-01-30 11:22:59 +09008130 }
8131
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008132 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008133 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008134 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8135 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8136 "proxy", curproxy->id);
8137 cfgerr++;
8138 goto out_uri_auth_compat;
8139 }
8140
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008141 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008142 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008143 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008144 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008145
Willy Tarreau95fa4692010-02-01 13:05:50 +01008146 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8147 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008148
8149 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008150 uri_auth_compat_req[i++] = "realm";
8151 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8152 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008153
Willy Tarreau95fa4692010-02-01 13:05:50 +01008154 uri_auth_compat_req[i++] = "unless";
8155 uri_auth_compat_req[i++] = "{";
8156 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8157 uri_auth_compat_req[i++] = "}";
8158 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008159
Willy Tarreauff011f22011-01-06 17:51:27 +01008160 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8161 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008162 cfgerr++;
8163 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008164 }
8165
Willy Tarreauff011f22011-01-06 17:51:27 +01008166 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008167
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008168 if (curproxy->uri_auth->auth_realm) {
8169 free(curproxy->uri_auth->auth_realm);
8170 curproxy->uri_auth->auth_realm = NULL;
8171 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008172
8173 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008174 }
8175out_uri_auth_compat:
8176
Dragan Dosen43885c72015-10-01 13:18:13 +02008177 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008178 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008179 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8180 if (!curproxy->conf.logformat_sd_string) {
8181 /* set the default logformat_sd_string */
8182 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8183 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008184 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008185 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008186 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008187
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008188 /* compile the log format */
8189 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008190 if (curproxy->conf.logformat_string != default_http_log_format &&
8191 curproxy->conf.logformat_string != default_tcp_log_format &&
8192 curproxy->conf.logformat_string != clf_http_log_format)
8193 free(curproxy->conf.logformat_string);
8194 curproxy->conf.logformat_string = NULL;
8195 free(curproxy->conf.lfs_file);
8196 curproxy->conf.lfs_file = NULL;
8197 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008198
8199 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8200 free(curproxy->conf.logformat_sd_string);
8201 curproxy->conf.logformat_sd_string = NULL;
8202 free(curproxy->conf.lfsd_file);
8203 curproxy->conf.lfsd_file = NULL;
8204 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008205 }
8206
Willy Tarreau62a61232013-04-12 18:13:46 +02008207 if (curproxy->conf.logformat_string) {
8208 curproxy->conf.args.ctx = ARGC_LOG;
8209 curproxy->conf.args.file = curproxy->conf.lfs_file;
8210 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008211 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008212 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008213 SMP_VAL_FE_LOG_END, &err)) {
8214 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8215 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8216 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008217 cfgerr++;
8218 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008219 curproxy->conf.args.file = NULL;
8220 curproxy->conf.args.line = 0;
8221 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008222
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008223 if (curproxy->conf.logformat_sd_string) {
8224 curproxy->conf.args.ctx = ARGC_LOGSD;
8225 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8226 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008227 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008228 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 +01008229 SMP_VAL_FE_LOG_END, &err)) {
8230 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8231 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8232 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008233 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008234 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8235 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8236 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8237 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008238 cfgerr++;
8239 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008240 curproxy->conf.args.file = NULL;
8241 curproxy->conf.args.line = 0;
8242 }
8243
Willy Tarreau62a61232013-04-12 18:13:46 +02008244 if (curproxy->conf.uniqueid_format_string) {
8245 curproxy->conf.args.ctx = ARGC_UIF;
8246 curproxy->conf.args.file = curproxy->conf.uif_file;
8247 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008248 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008249 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 +01008250 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8251 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8252 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8253 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008254 cfgerr++;
8255 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008256 curproxy->conf.args.file = NULL;
8257 curproxy->conf.args.line = 0;
8258 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008259
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008260 /* only now we can check if some args remain unresolved.
8261 * This must be done after the users and groups resolution.
8262 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008263 cfgerr += smp_resolve_args(curproxy);
8264 if (!cfgerr)
8265 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008266
Willy Tarreau2738a142006-07-08 17:28:09 +02008267 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008268 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008269 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008270 (!curproxy->timeout.connect ||
8271 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008272 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008273 " | While not properly invalid, you will certainly encounter various problems\n"
8274 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008275 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008276 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008277 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008278 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008279
Willy Tarreau1fa31262007-12-03 00:36:16 +01008280 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8281 * We must still support older configurations, so let's find out whether those
8282 * parameters have been set or must be copied from contimeouts.
8283 */
8284 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008285 if (!curproxy->timeout.tarpit ||
8286 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008287 /* tarpit timeout not set. We search in the following order:
8288 * default.tarpit, curr.connect, default.connect.
8289 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008290 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008291 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008292 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008293 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008294 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008295 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008296 }
8297 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008298 (!curproxy->timeout.queue ||
8299 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008300 /* queue timeout not set. We search in the following order:
8301 * default.queue, curr.connect, default.connect.
8302 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008303 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008304 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008305 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008306 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008307 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008308 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008309 }
8310 }
8311
Willy Tarreau1620ec32011-08-06 17:05:02 +02008312 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008313 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008314 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008315 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008316 }
8317
Willy Tarreau215663d2014-06-13 18:30:23 +02008318 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8319 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8320 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8321 proxy_type_str(curproxy), curproxy->id);
8322 err_code |= ERR_WARN;
8323 }
8324
Willy Tarreau193b8c62012-11-22 00:17:38 +01008325 /* ensure that cookie capture length is not too large */
8326 if (curproxy->capture_len >= global.tune.cookie_len) {
8327 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8328 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8329 err_code |= ERR_WARN;
8330 curproxy->capture_len = global.tune.cookie_len - 1;
8331 }
8332
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008333 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008334 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008335 curproxy->req_cap_pool = create_pool("ptrcap",
8336 curproxy->nb_req_cap * sizeof(char *),
8337 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008338 }
8339
8340 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008341 curproxy->rsp_cap_pool = create_pool("ptrcap",
8342 curproxy->nb_rsp_cap * sizeof(char *),
8343 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008344 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008345
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008346 switch (curproxy->load_server_state_from_file) {
8347 case PR_SRV_STATE_FILE_UNSPEC:
8348 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8349 break;
8350 case PR_SRV_STATE_FILE_GLOBAL:
8351 if (!global.server_state_file) {
8352 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",
8353 curproxy->id);
8354 err_code |= ERR_WARN;
8355 }
8356 break;
8357 }
8358
Willy Tarreaubaaee002006-06-26 02:48:02 +02008359 /* first, we will invert the servers list order */
8360 newsrv = NULL;
8361 while (curproxy->srv) {
8362 struct server *next;
8363
8364 next = curproxy->srv->next;
8365 curproxy->srv->next = newsrv;
8366 newsrv = curproxy->srv;
8367 if (!next)
8368 break;
8369 curproxy->srv = next;
8370 }
8371
Willy Tarreau17edc812014-01-03 12:14:34 +01008372 /* Check that no server name conflicts. This causes trouble in the stats.
8373 * We only emit a warning for the first conflict affecting each server,
8374 * in order to avoid combinatory explosion if all servers have the same
8375 * name. We do that only for servers which do not have an explicit ID,
8376 * because these IDs were made also for distinguishing them and we don't
8377 * want to annoy people who correctly manage them.
8378 */
8379 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8380 struct server *other_srv;
8381
8382 if (newsrv->puid)
8383 continue;
8384
8385 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8386 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8387 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8388 newsrv->conf.file, newsrv->conf.line,
8389 proxy_type_str(curproxy), curproxy->id,
8390 newsrv->id, other_srv->conf.line);
8391 break;
8392 }
8393 }
8394 }
8395
Willy Tarreaudd701652010-05-25 23:03:02 +02008396 /* assign automatic UIDs to servers which don't have one yet */
8397 next_id = 1;
8398 newsrv = curproxy->srv;
8399 while (newsrv != NULL) {
8400 if (!newsrv->puid) {
8401 /* server ID not set, use automatic numbering with first
8402 * spare entry starting with next_svid.
8403 */
8404 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8405 newsrv->conf.id.key = newsrv->puid = next_id;
8406 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8407 }
8408 next_id++;
8409 newsrv = newsrv->next;
8410 }
8411
Willy Tarreau20697042007-11-15 23:26:18 +01008412 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008413 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008414
Willy Tarreau62c3be22012-01-20 13:12:32 +01008415 /*
8416 * If this server supports a maxconn parameter, it needs a dedicated
8417 * tasks to fill the emptied slots when a connection leaves.
8418 * Also, resolve deferred tracking dependency if needed.
8419 */
8420 newsrv = curproxy->srv;
8421 while (newsrv != NULL) {
8422 if (newsrv->minconn > newsrv->maxconn) {
8423 /* Only 'minconn' was specified, or it was higher than or equal
8424 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8425 * this will avoid further useless expensive computations.
8426 */
8427 newsrv->maxconn = newsrv->minconn;
8428 } else if (newsrv->maxconn && !newsrv->minconn) {
8429 /* minconn was not specified, so we set it to maxconn */
8430 newsrv->minconn = newsrv->maxconn;
8431 }
8432
Willy Tarreau17d45382016-12-22 21:16:08 +01008433 /* this will also properly set the transport layer for prod and checks */
8434 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8435 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8436 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8437 }
Emeric Brun94324a42012-10-11 14:00:19 +02008438
Willy Tarreau2f075e92013-12-03 11:11:34 +01008439 /* set the check type on the server */
8440 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8441
Willy Tarreau62c3be22012-01-20 13:12:32 +01008442 if (newsrv->trackit) {
8443 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008444 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008445 char *pname, *sname;
8446
8447 pname = newsrv->trackit;
8448 sname = strrchr(pname, '/');
8449
8450 if (sname)
8451 *sname++ = '\0';
8452 else {
8453 sname = pname;
8454 pname = NULL;
8455 }
8456
8457 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008458 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008459 if (!px) {
8460 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8461 proxy_type_str(curproxy), curproxy->id,
8462 newsrv->id, pname);
8463 cfgerr++;
8464 goto next_srv;
8465 }
8466 } else
8467 px = curproxy;
8468
8469 srv = findserver(px, sname);
8470 if (!srv) {
8471 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8472 proxy_type_str(curproxy), curproxy->id,
8473 newsrv->id, sname);
8474 cfgerr++;
8475 goto next_srv;
8476 }
8477
Willy Tarreau32091232014-05-16 13:52:00 +02008478 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8479 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8480 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008481 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008482 "tracking as it does not have any check nor agent enabled.\n",
8483 proxy_type_str(curproxy), curproxy->id,
8484 newsrv->id, px->id, srv->id);
8485 cfgerr++;
8486 goto next_srv;
8487 }
8488
8489 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8490
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008491 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008492 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8493 "belongs to a tracking chain looping back to %s/%s.\n",
8494 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008495 newsrv->id, px->id, srv->id, px->id,
8496 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008497 cfgerr++;
8498 goto next_srv;
8499 }
8500
8501 if (curproxy != px &&
8502 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8503 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8504 "tracking: disable-on-404 option inconsistency.\n",
8505 proxy_type_str(curproxy), curproxy->id,
8506 newsrv->id, px->id, srv->id);
8507 cfgerr++;
8508 goto next_srv;
8509 }
8510
Willy Tarreau62c3be22012-01-20 13:12:32 +01008511 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008512 newsrv->tracknext = srv->trackers;
8513 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008514
8515 free(newsrv->trackit);
8516 newsrv->trackit = NULL;
8517 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008518
Willy Tarreau62c3be22012-01-20 13:12:32 +01008519 next_srv:
8520 newsrv = newsrv->next;
8521 }
8522
Olivier Houchard4e694042017-03-14 20:01:29 +01008523 /*
8524 * Try to generate dynamic cookies for servers now.
8525 * It couldn't be done earlier, since at the time we parsed
8526 * the server line, we may not have known yet that we
8527 * should use dynamic cookies, or the secret key may not
8528 * have been provided yet.
8529 */
8530 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8531 newsrv = curproxy->srv;
8532 while (newsrv != NULL) {
8533 srv_set_dyncookie(newsrv);
8534 newsrv = newsrv->next;
8535 }
8536
8537 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008538 /* We have to initialize the server lookup mechanism depending
8539 * on what LB algorithm was choosen.
8540 */
8541
8542 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8543 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8544 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008545 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8546 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8547 init_server_map(curproxy);
8548 } else {
8549 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8550 fwrr_init_server_groups(curproxy);
8551 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008552 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008553
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008554 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008555 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8556 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8557 fwlc_init_server_tree(curproxy);
8558 } else {
8559 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8560 fas_init_server_tree(curproxy);
8561 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008562 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008563
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008564 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008565 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8566 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8567 chash_init_server_tree(curproxy);
8568 } else {
8569 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8570 init_server_map(curproxy);
8571 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008572 break;
8573 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008574 HA_SPIN_INIT(&curproxy->lbprm.lock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02008575
8576 if (curproxy->options & PR_O_LOGASAP)
8577 curproxy->to_log &= ~LW_BYTES;
8578
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008579 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008580 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8581 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008582 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8583 proxy_type_str(curproxy), curproxy->id);
8584 err_code |= ERR_WARN;
8585 }
8586
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008587 if (curproxy->mode != PR_MODE_HTTP) {
8588 int optnum;
8589
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008590 if (curproxy->uri_auth) {
8591 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8592 proxy_type_str(curproxy), curproxy->id);
8593 err_code |= ERR_WARN;
8594 curproxy->uri_auth = NULL;
8595 }
8596
Willy Tarreaude7dc882017-03-10 11:49:21 +01008597 if (curproxy->capture_name) {
8598 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8599 proxy_type_str(curproxy), curproxy->id);
8600 err_code |= ERR_WARN;
8601 }
8602
8603 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8604 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8605 proxy_type_str(curproxy), curproxy->id);
8606 err_code |= ERR_WARN;
8607 }
8608
8609 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8610 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8611 proxy_type_str(curproxy), curproxy->id);
8612 err_code |= ERR_WARN;
8613 }
8614
8615 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8616 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8617 proxy_type_str(curproxy), curproxy->id);
8618 err_code |= ERR_WARN;
8619 }
8620
8621 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8622 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8623 proxy_type_str(curproxy), curproxy->id);
8624 err_code |= ERR_WARN;
8625 }
8626
Willy Tarreau87cf5142011-08-19 22:57:24 +02008627 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008628 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8629 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8630 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008631 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008632 }
8633
8634 if (curproxy->options & PR_O_ORGTO) {
8635 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8636 "originalto", proxy_type_str(curproxy), curproxy->id);
8637 err_code |= ERR_WARN;
8638 curproxy->options &= ~PR_O_ORGTO;
8639 }
8640
8641 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8642 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8643 (curproxy->cap & cfg_opts[optnum].cap) &&
8644 (curproxy->options & cfg_opts[optnum].val)) {
8645 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8646 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8647 err_code |= ERR_WARN;
8648 curproxy->options &= ~cfg_opts[optnum].val;
8649 }
8650 }
8651
8652 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8653 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8654 (curproxy->cap & cfg_opts2[optnum].cap) &&
8655 (curproxy->options2 & cfg_opts2[optnum].val)) {
8656 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8657 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8658 err_code |= ERR_WARN;
8659 curproxy->options2 &= ~cfg_opts2[optnum].val;
8660 }
8661 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008662
Willy Tarreau29fbe512015-08-20 19:35:14 +02008663#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008664 if (curproxy->conn_src.bind_hdr_occ) {
8665 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008666 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008667 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008668 err_code |= ERR_WARN;
8669 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008670#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008671 }
8672
Willy Tarreaubaaee002006-06-26 02:48:02 +02008673 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008674 * ensure that we're not cross-dressing a TCP server into HTTP.
8675 */
8676 newsrv = curproxy->srv;
8677 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008678 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008679 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8680 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008681 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008682 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008683
Willy Tarreau0cec3312011-10-31 13:49:26 +01008684 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8685 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8686 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8687 err_code |= ERR_WARN;
8688 }
8689
Willy Tarreauc93cd162014-05-13 15:54:22 +02008690 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008691 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8692 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8693 err_code |= ERR_WARN;
8694 }
8695
Willy Tarreau29fbe512015-08-20 19:35:14 +02008696#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008697 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8698 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008699 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 +01008700 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008701 err_code |= ERR_WARN;
8702 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008703#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008704
8705 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8706 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8707 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8708 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8709 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8710 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",
8711 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8712 err_code |= ERR_WARN;
8713 }
8714
8715
8716 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8717 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",
8718 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8719 err_code |= ERR_WARN;
8720 }
8721 }
8722
Willy Tarreau21d2af32008-02-14 20:25:24 +01008723 newsrv = newsrv->next;
8724 }
8725
Willy Tarreaue42bd962014-09-16 16:21:19 +02008726 /* check if we have a frontend with "tcp-request content" looking at L7
8727 * with no inspect-delay
8728 */
8729 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008730 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8731 if (arule->action == ACT_TCP_CAPTURE &&
8732 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008733 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008734 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8735 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008736 break;
8737 }
8738
Christopher Faulete4e830d2017-09-18 14:51:41 +02008739 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008740 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8741 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8742 " This means that these rules will randomly find their contents. This can be fixed by"
8743 " setting the tcp-request inspect-delay.\n",
8744 proxy_type_str(curproxy), curproxy->id);
8745 err_code |= ERR_WARN;
8746 }
8747 }
8748
Christopher Fauletd7c91962015-04-30 11:48:27 +02008749 /* Check filter configuration, if any */
8750 cfgerr += flt_check(curproxy);
8751
Willy Tarreauc1a21672009-08-16 22:37:44 +02008752 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008753 if (!curproxy->accept)
8754 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008755
Willy Tarreauc1a21672009-08-16 22:37:44 +02008756 if (curproxy->tcp_req.inspect_delay ||
8757 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008758 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008759
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008760 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008761 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008762 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008763 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008764
8765 /* both TCP and HTTP must check switching rules */
8766 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008767
8768 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008769 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008770 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8771 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 +01008772 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008773 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8774 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008775 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008776 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008777 }
8778
8779 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008780 if (curproxy->tcp_req.inspect_delay ||
8781 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8782 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8783
Emeric Brun97679e72010-09-23 17:56:44 +02008784 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8785 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8786
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008787 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008788 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008789 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008790 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008791
8792 /* If the backend does requires RDP cookie persistence, we have to
8793 * enable the corresponding analyser.
8794 */
8795 if (curproxy->options2 & PR_O2_RDPC_PRST)
8796 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008797
8798 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008799 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008800 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8801 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 +01008802 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008803 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8804 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008805 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008806 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008807 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008808 }
8809
8810 /***********************************************************/
8811 /* At this point, target names have already been resolved. */
8812 /***********************************************************/
8813
8814 /* Check multi-process mode compatibility */
8815
8816 if (global.nbproc > 1 && global.stats_fe) {
8817 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8818 unsigned long mask;
8819
8820 mask = nbits(global.nbproc);
8821 if (global.stats_fe->bind_proc)
8822 mask &= global.stats_fe->bind_proc;
8823
8824 if (bind_conf->bind_proc)
8825 mask &= bind_conf->bind_proc;
8826
8827 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008828 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008829 break;
8830 }
8831 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8832 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");
8833 }
8834 }
8835
8836 /* Make each frontend inherit bind-process from its listeners when not specified. */
8837 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8838 if (curproxy->bind_proc)
8839 continue;
8840
8841 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8842 unsigned long mask;
8843
Willy Tarreaue428b082015-05-04 21:57:58 +02008844 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008845 curproxy->bind_proc |= mask;
8846 }
8847
8848 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008849 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008850 }
8851
8852 if (global.stats_fe) {
8853 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8854 unsigned long mask;
8855
Cyril Bonté06181952016-02-24 00:14:54 +01008856 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008857 global.stats_fe->bind_proc |= mask;
8858 }
8859 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008860 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008861 }
8862
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008863 /* propagate bindings from frontends to backends. Don't do it if there
8864 * are any fatal errors as we must not call it with unresolved proxies.
8865 */
8866 if (!cfgerr) {
8867 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8868 if (curproxy->cap & PR_CAP_FE)
8869 propagate_processes(curproxy, NULL);
8870 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008871 }
8872
8873 /* Bind each unbound backend to all processes when not specified. */
8874 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8875 if (curproxy->bind_proc)
8876 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008877 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008878 }
8879
8880 /*******************************************************/
8881 /* At this step, all proxies have a non-null bind_proc */
8882 /*******************************************************/
8883
8884 /* perform the final checks before creating tasks */
8885
8886 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8887 struct listener *listener;
8888 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008889
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008890 /* Configure SSL for each bind line.
8891 * Note: if configuration fails at some point, the ->ctx member
8892 * remains NULL so that listeners can later detach.
8893 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008894 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008895 if (bind_conf->xprt->prepare_bind_conf &&
8896 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008897 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008898 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008899
Willy Tarreaue6b98942007-10-29 01:09:36 +01008900 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008901 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008902 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008903 int nbproc;
8904
8905 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008906 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008907 nbits(global.nbproc));
8908
8909 if (!nbproc) /* no intersection between listener and frontend */
8910 nbproc = 1;
8911
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008912 if (!listener->luid) {
8913 /* listener ID not set, use automatic numbering with first
8914 * spare entry starting with next_luid.
8915 */
8916 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8917 listener->conf.id.key = listener->luid = next_id;
8918 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008919 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008920 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008921
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008922 /* enable separate counters */
8923 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008924 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008925 if (!listener->name)
8926 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008927 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008928
Willy Tarreaue6b98942007-10-29 01:09:36 +01008929 if (curproxy->options & PR_O_TCP_NOLING)
8930 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008931 if (!listener->maxconn)
8932 listener->maxconn = curproxy->maxconn;
8933 if (!listener->backlog)
8934 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008935 if (!listener->maxaccept)
8936 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8937
8938 /* we want to have an optimal behaviour on single process mode to
8939 * maximize the work at once, but in multi-process we want to keep
8940 * some fairness between processes, so we target half of the max
8941 * number of events to be balanced over all the processes the proxy
8942 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8943 * used to disable the limit.
8944 */
8945 if (listener->maxaccept > 0) {
8946 if (nbproc > 1)
8947 listener->maxaccept = (listener->maxaccept + 1) / 2;
8948 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8949 }
8950
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008951 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008952 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008953 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008954
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008955 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008956 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008957
Willy Tarreau620408f2016-10-21 16:37:51 +02008958 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8959 listener->options |= LI_O_TCP_L5_RULES;
8960
Willy Tarreaude3041d2010-05-31 10:56:17 +02008961 if (curproxy->mon_mask.s_addr)
8962 listener->options |= LI_O_CHK_MONNET;
8963
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008964 /* smart accept mode is automatic in HTTP mode */
8965 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008966 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008967 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8968 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008969 }
8970
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008971 /* Release unused SSL configs */
8972 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008973 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8974 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008975 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008976
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008977 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008978 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008979 int count, maxproc = 0;
8980
8981 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008982 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008983 if (count > maxproc)
8984 maxproc = count;
8985 }
8986 /* backends have 0, frontends have 1 or more */
8987 if (maxproc != 1)
8988 Warning("Proxy '%s': in multi-process mode, stats will be"
8989 " limited to process assigned to the current request.\n",
8990 curproxy->id);
8991
Willy Tarreau102df612014-05-07 23:56:38 +02008992 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8993 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8994 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008995 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008996 }
Willy Tarreau102df612014-05-07 23:56:38 +02008997 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8998 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8999 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009000 }
9001 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009002
9003 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02009004 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02009005 if (curproxy->task) {
9006 curproxy->task->context = curproxy;
9007 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009008 } else {
9009 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9010 curproxy->id);
9011 cfgerr++;
9012 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009013 }
9014
Willy Tarreaufbb78422011-06-05 15:38:35 +02009015 /* automatically compute fullconn if not set. We must not do it in the
9016 * loop above because cross-references are not yet fully resolved.
9017 */
9018 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9019 /* If <fullconn> is not set, let's set it to 10% of the sum of
9020 * the possible incoming frontend's maxconns.
9021 */
9022 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009023 /* we have the sum of the maxconns in <total>. We only
9024 * keep 10% of that sum to set the default fullconn, with
9025 * a hard minimum of 1 (to avoid a divide by zero).
9026 */
Emeric Brun3f783572017-01-12 11:21:28 +01009027 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009028 if (!curproxy->fullconn)
9029 curproxy->fullconn = 1;
9030 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009031 }
9032
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009033 /*
9034 * Recount currently required checks.
9035 */
9036
9037 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9038 int optnum;
9039
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009040 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9041 if (curproxy->options & cfg_opts[optnum].val)
9042 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009043
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009044 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9045 if (curproxy->options2 & cfg_opts2[optnum].val)
9046 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009047 }
9048
Willy Tarreau0fca4832015-05-01 19:12:05 +02009049 /* compute the required process bindings for the peers */
9050 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9051 if (curproxy->table.peers.p)
9052 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9053
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009054 if (cfg_peers) {
9055 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009056 struct peer *p, *pb;
9057
Willy Tarreau1e273012015-05-01 19:15:17 +02009058 /* Remove all peers sections which don't have a valid listener,
9059 * which are not used by any table, or which are bound to more
9060 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009061 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009062 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009063 while (*last) {
9064 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009065
9066 if (curpeers->state == PR_STSTOPPED) {
9067 /* the "disabled" keyword was present */
9068 if (curpeers->peers_fe)
9069 stop_proxy(curpeers->peers_fe);
9070 curpeers->peers_fe = NULL;
9071 }
9072 else if (!curpeers->peers_fe) {
9073 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9074 curpeers->id, localpeer);
9075 }
David Carliere6c39412015-07-02 07:00:17 +00009076 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009077 /* either it's totally stopped or too much used */
9078 if (curpeers->peers_fe->bind_proc) {
9079 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009080 "running in different processes (%d different ones). "
9081 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009082 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009083 cfgerr++;
9084 }
9085 stop_proxy(curpeers->peers_fe);
9086 curpeers->peers_fe = NULL;
9087 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009088 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009089 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009090 last = &curpeers->next;
9091 continue;
9092 }
9093
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009094 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009095 p = curpeers->remote;
9096 while (p) {
9097 pb = p->next;
9098 free(p->id);
9099 free(p);
9100 p = pb;
9101 }
9102
9103 /* Destroy and unlink this curpeers section.
9104 * Note: curpeers is backed up into *last.
9105 */
9106 free(curpeers->id);
9107 curpeers = curpeers->next;
9108 free(*last);
9109 *last = curpeers;
9110 }
9111 }
9112
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009113 /* initialize stick-tables on backend capable proxies. This must not
9114 * be done earlier because the data size may be discovered while parsing
9115 * other proxies.
9116 */
9117 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9118 if (curproxy->state == PR_STSTOPPED)
9119 continue;
9120
9121 if (!stktable_init(&curproxy->table)) {
9122 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9123 cfgerr++;
9124 }
9125 }
9126
Simon Horman0d16a402015-01-30 11:22:58 +09009127 if (mailers) {
9128 struct mailers *curmailers = mailers, **last;
9129 struct mailer *m, *mb;
9130
9131 /* Remove all mailers sections which don't have a valid listener.
9132 * This can happen when a mailers section is never referenced.
9133 */
9134 last = &mailers;
9135 while (*last) {
9136 curmailers = *last;
9137 if (curmailers->users) {
9138 last = &curmailers->next;
9139 continue;
9140 }
9141
9142 Warning("Removing incomplete section 'mailers %s'.\n",
9143 curmailers->id);
9144
9145 m = curmailers->mailer_list;
9146 while (m) {
9147 mb = m->next;
9148 free(m->id);
9149 free(m);
9150 m = mb;
9151 }
9152
9153 /* Destroy and unlink this curmailers section.
9154 * Note: curmailers is backed up into *last.
9155 */
9156 free(curmailers->id);
9157 curmailers = curmailers->next;
9158 free(*last);
9159 *last = curmailers;
9160 }
9161 }
9162
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009163 /* Update server_state_file_name to backend name if backend is supposed to use
9164 * a server-state file locally defined and none has been provided */
9165 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9166 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9167 curproxy->server_state_file_name == NULL)
9168 curproxy->server_state_file_name = strdup(curproxy->id);
9169 }
9170
Willy Tarreau34eb6712011-10-24 18:15:04 +02009171 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009172 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009173 MEM_F_SHARED);
9174
William Lallemand48b4bb42017-10-23 14:36:34 +02009175 list_for_each_entry(postparser, &postparsers, list) {
9176 if (postparser->func)
9177 cfgerr += postparser->func();
9178 }
9179
Willy Tarreaubb925012009-07-23 13:36:36 +02009180 if (cfgerr > 0)
9181 err_code |= ERR_ALERT | ERR_FATAL;
9182 out:
9183 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009184}
9185
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009186/*
9187 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9188 * parsing sessions.
9189 */
9190void cfg_register_keywords(struct cfg_kw_list *kwl)
9191{
9192 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9193}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009194
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009195/*
9196 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9197 */
9198void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9199{
9200 LIST_DEL(&kwl->list);
9201 LIST_INIT(&kwl->list);
9202}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009203
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009204/* this function register new section in the haproxy configuration file.
9205 * <section_name> is the name of this new section and <section_parser>
9206 * is the called parser. If two section declaration have the same name,
9207 * only the first declared is used.
9208 */
9209int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009210 int (*section_parser)(const char *, int, char **, int),
9211 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009212{
9213 struct cfg_section *cs;
9214
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009215 list_for_each_entry(cs, &sections, list) {
9216 if (strcmp(cs->section_name, section_name) == 0) {
9217 Alert("register section '%s': already registered.\n", section_name);
9218 return 0;
9219 }
9220 }
9221
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009222 cs = calloc(1, sizeof(*cs));
9223 if (!cs) {
9224 Alert("register section '%s': out of memory.\n", section_name);
9225 return 0;
9226 }
9227
9228 cs->section_name = section_name;
9229 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009230 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009231
9232 LIST_ADDQ(&sections, &cs->list);
9233
9234 return 1;
9235}
9236
William Lallemand48b4bb42017-10-23 14:36:34 +02009237/* this function register a new function which will be called once the haproxy
9238 * configuration file has been parsed. It's useful to check dependencies
9239 * between sections or to resolve items once everything is parsed.
9240 */
9241int cfg_register_postparser(char *name, int (*func)())
9242{
9243 struct cfg_postparser *cp;
9244
9245 cp = calloc(1, sizeof(*cp));
9246 if (!cp) {
9247 Alert("register postparser '%s': out of memory.\n", name);
9248 return 0;
9249 }
9250 cp->name = name;
9251 cp->func = func;
9252
9253 LIST_ADDQ(&postparsers, &cp->list);
9254
9255 return 1;
9256}
9257
Willy Tarreaubaaee002006-06-26 02:48:02 +02009258/*
David Carlier845efb52015-09-25 11:49:18 +01009259 * free all config section entries
9260 */
9261void cfg_unregister_sections(void)
9262{
9263 struct cfg_section *cs, *ics;
9264
9265 list_for_each_entry_safe(cs, ics, &sections, list) {
9266 LIST_DEL(&cs->list);
9267 free(cs);
9268 }
9269}
9270
Christopher Faulet7110b402016-10-26 11:09:44 +02009271void cfg_backup_sections(struct list *backup_sections)
9272{
9273 struct cfg_section *cs, *ics;
9274
9275 list_for_each_entry_safe(cs, ics, &sections, list) {
9276 LIST_DEL(&cs->list);
9277 LIST_ADDQ(backup_sections, &cs->list);
9278 }
9279}
9280
9281void cfg_restore_sections(struct list *backup_sections)
9282{
9283 struct cfg_section *cs, *ics;
9284
9285 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9286 LIST_DEL(&cs->list);
9287 LIST_ADDQ(&sections, &cs->list);
9288 }
9289}
9290
Willy Tarreau659fbf02016-05-26 17:55:28 +02009291__attribute__((constructor))
9292static void cfgparse_init(void)
9293{
9294 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009295 cfg_register_section("listen", cfg_parse_listen, NULL);
9296 cfg_register_section("frontend", cfg_parse_listen, NULL);
9297 cfg_register_section("backend", cfg_parse_listen, NULL);
9298 cfg_register_section("defaults", cfg_parse_listen, NULL);
9299 cfg_register_section("global", cfg_parse_global, NULL);
9300 cfg_register_section("userlist", cfg_parse_users, NULL);
9301 cfg_register_section("peers", cfg_parse_peers, NULL);
9302 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9303 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9304 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009305}
9306
David Carlier845efb52015-09-25 11:49:18 +01009307/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009308 * Local variables:
9309 * c-indent-level: 8
9310 * c-basic-offset: 8
9311 * End:
9312 */