blob: 83bab1ade3c103769a9fd12599dfbeda83fc4a07 [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 Faulet26028f62017-11-22 15:01:51 +0100599int parse_process_number(const char *arg, unsigned long *proc, int *autoinc, char **err)
Christopher Faulet62519022017-10-16 15:49:32 +0200600{
Christopher Faulet26028f62017-11-22 15:01:51 +0100601 if (autoinc) {
602 *autoinc = 0;
603 if (strncmp(arg, "auto:", 5) == 0) {
604 arg += 5;
605 *autoinc = 1;
606 }
607 }
608
Christopher Faulet62519022017-10-16 15:49:32 +0200609 if (strcmp(arg, "all") == 0)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100610 *proc |= ~0UL;
Christopher Faulet62519022017-10-16 15:49:32 +0200611 else if (strcmp(arg, "odd") == 0)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100612 *proc |= ~0UL/3UL; /* 0x555....555 */
Christopher Faulet62519022017-10-16 15:49:32 +0200613 else if (strcmp(arg, "even") == 0)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100614 *proc |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Christopher Faulet62519022017-10-16 15:49:32 +0200615 else {
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100616 char *dash;
617 unsigned int low, high;
618
Christopher Faulet5ab51772017-11-22 11:21:58 +0100619 if (!isdigit((int)*arg)) {
620 memprintf(err, "'%s' is not a valid PROC number.\n", arg);
621 return -1;
622 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100623
624 low = high = str2uic(arg);
625 if ((dash = strchr(arg, '-')) != NULL)
Christopher Fauletff4121f2017-11-22 16:38:49 +0100626 high = ((!*(dash+1)) ? LONGBITS : str2uic(dash + 1));
627
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100628 if (high < low) {
629 unsigned int swap = low;
630 low = high;
631 high = swap;
632 }
633
Christopher Faulet5ab51772017-11-22 11:21:58 +0100634 if (low < 1 || low > LONGBITS || high > LONGBITS) {
635 memprintf(err, "'%s' is not a valid PROC number/range."
636 " It supports PROC numbers from 1 to %d.\n",
637 arg, LONGBITS);
638 return 1;
639 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100640
641 for (;low <= high; low++)
Christopher Faulet5ab51772017-11-22 11:21:58 +0100642 *proc |= 1UL << (low-1);
Christopher Faulet62519022017-10-16 15:49:32 +0200643 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +0100644
645 end:
Christopher Faulet5ab51772017-11-22 11:21:58 +0100646 return 0;
Christopher Faulet62519022017-10-16 15:49:32 +0200647}
648
649/* Parse cpu sets. Each CPU set is either a unique number between 0 and
650 * <LONGBITS> or a range with two such numbers delimited by a dash
651 * ('-'). Multiple CPU numbers or ranges may be specified. On success, it
652 * returns 0. otherwise it returns 1 with an error message in <err>.
653 */
654static unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
655{
656 int cur_arg = 0;
657
658 *cpu_set = 0;
659 while (*args[cur_arg]) {
660 char *dash;
661 unsigned int low, high;
662
663 if (!isdigit((int)*args[cur_arg])) {
664 memprintf(err, "'%s' is not a CPU range.\n", args[cur_arg]);
665 return -1;
666 }
667
668 low = high = str2uic(args[cur_arg]);
669 if ((dash = strchr(args[cur_arg], '-')) != NULL)
Christopher Fauletff4121f2017-11-22 16:38:49 +0100670 high = ((!*(dash+1)) ? LONGBITS-1 : str2uic(dash + 1));
Christopher Faulet62519022017-10-16 15:49:32 +0200671
672 if (high < low) {
673 unsigned int swap = low;
674 low = high;
675 high = swap;
676 }
677
678 if (high >= LONGBITS) {
679 memprintf(err, "supports CPU numbers from 0 to %d.\n", LONGBITS - 1);
680 return 1;
681 }
682
683 while (low <= high)
684 *cpu_set |= 1UL << low++;
685
686 cur_arg++;
687 }
688 return 0;
689}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 * parse a line in a <global> section. Returns the error code, 0 if OK, or
692 * any combination of :
693 * - ERR_ABORT: must abort ASAP
694 * - ERR_FATAL: we can continue parsing but not start the service
695 * - ERR_WARN: a warning has been emitted
696 * - ERR_ALERT: an alert has been emitted
697 * Only the two first ones can stop processing, the two others are just
698 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200700int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701{
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200703 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704
705 if (!strcmp(args[0], "global")) { /* new section */
706 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200707 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 }
710 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200711 if (alertif_too_many_args(0, file, linenum, args, &err_code))
712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713 global.mode |= MODE_DAEMON;
714 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200715 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200716 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200717 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200718 if (*args[1]) {
719 if (!strcmp(args[1], "exit-on-failure")) {
720 global.tune.options |= GTUNE_EXIT_ONFAILURE;
721 } else {
722 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
725 }
726 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200727 global.mode |= MODE_MWORKER;
728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(0, file, linenum, args, &err_code))
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 global.mode |= MODE_DEBUG;
733 }
734 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200735 if (alertif_too_many_args(0, file, linenum, args, &err_code))
736 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100737 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200739 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200740 if (alertif_too_many_args(0, file, linenum, args, &err_code))
741 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100742 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200745 if (alertif_too_many_args(0, file, linenum, args, &err_code))
746 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100747 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100749 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200750 if (alertif_too_many_args(0, file, linenum, args, &err_code))
751 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100752 global.tune.options &= ~GTUNE_USE_SPLICE;
753 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200754 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200755 if (alertif_too_many_args(0, file, linenum, args, &err_code))
756 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200757 global.tune.options &= ~GTUNE_USE_GAI;
758 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000759 else if (!strcmp(args[0], "noreuseport")) {
760 if (alertif_too_many_args(0, file, linenum, args, &err_code))
761 goto out;
762 global.tune.options &= ~GTUNE_USE_REUSEPORT;
763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200765 if (alertif_too_many_args(0, file, linenum, args, &err_code))
766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 global.mode |= MODE_QUIET;
768 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200769 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200770 if (alertif_too_many_args(1, file, linenum, args, &err_code))
771 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200772 if (global.tune.maxpollevents != 0) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200781 }
782 global.tune.maxpollevents = atol(args[1]);
783 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100784 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200785 if (alertif_too_many_args(1, file, linenum, args, &err_code))
786 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100787 if (global.tune.maxaccept != 0) {
788 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200789 err_code |= ERR_ALERT;
790 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100791 }
792 if (*(args[1]) == 0) {
793 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100796 }
797 global.tune.maxaccept = atol(args[1]);
798 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200799 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200800 if (alertif_too_many_args(1, file, linenum, args, &err_code))
801 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200802 if (*(args[1]) == 0) {
803 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
804 err_code |= ERR_ALERT | ERR_FATAL;
805 goto out;
806 }
807 global.tune.chksize = atol(args[1]);
808 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100809 else if (!strcmp(args[0], "tune.recv_enough")) {
810 if (alertif_too_many_args(1, file, linenum, args, &err_code))
811 goto out;
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.recv_enough = atol(args[1]);
818 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100819 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200820 if (alertif_too_many_args(1, file, linenum, args, &err_code))
821 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
826 }
827 global.tune.buf_limit = atol(args[1]);
828 if (global.tune.buf_limit) {
829 if (global.tune.buf_limit < 3)
830 global.tune.buf_limit = 3;
831 if (global.tune.buf_limit <= global.tune.reserved_bufs)
832 global.tune.buf_limit = global.tune.reserved_bufs + 1;
833 }
834 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100835 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100838 if (*(args[1]) == 0) {
839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 global.tune.reserved_bufs = atol(args[1]);
844 if (global.tune.reserved_bufs < 2)
845 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100846 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
847 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100848 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200849 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200850 if (alertif_too_many_args(1, file, linenum, args, &err_code))
851 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200858 if (global.tune.bufsize <= 0) {
859 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200863 }
864 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200865 if (alertif_too_many_args(1, file, linenum, args, &err_code))
866 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200867 if (*(args[1]) == 0) {
868 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200873 if (global.tune.maxrewrite < 0) {
874 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
875 err_code |= ERR_ALERT | ERR_FATAL;
876 goto out;
877 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200878 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100879 else if (!strcmp(args[0], "tune.idletimer")) {
880 unsigned int idle;
881 const char *res;
882
William Lallemand1a748ae2015-05-19 16:37:23 +0200883 if (alertif_too_many_args(1, file, linenum, args, &err_code))
884 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890
891 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
892 if (res) {
893 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
894 file, linenum, *res, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
898
899 if (idle > 65535) {
900 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 global.tune.idle_timer = idle;
905 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100906 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200907 if (alertif_too_many_args(1, file, linenum, args, &err_code))
908 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100909 if (global.tune.client_rcvbuf != 0) {
910 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT;
912 goto out;
913 }
914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919 global.tune.client_rcvbuf = atol(args[1]);
920 }
921 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200922 if (alertif_too_many_args(1, file, linenum, args, &err_code))
923 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100924 if (global.tune.server_rcvbuf != 0) {
925 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
926 err_code |= ERR_ALERT;
927 goto out;
928 }
929 if (*(args[1]) == 0) {
930 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT | ERR_FATAL;
932 goto out;
933 }
934 global.tune.server_rcvbuf = atol(args[1]);
935 }
936 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200937 if (alertif_too_many_args(1, file, linenum, args, &err_code))
938 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100939 if (global.tune.client_sndbuf != 0) {
940 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
941 err_code |= ERR_ALERT;
942 goto out;
943 }
944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949 global.tune.client_sndbuf = atol(args[1]);
950 }
951 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200952 if (alertif_too_many_args(1, file, linenum, args, &err_code))
953 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100954 if (global.tune.server_sndbuf != 0) {
955 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT;
957 goto out;
958 }
959 if (*(args[1]) == 0) {
960 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
961 err_code |= ERR_ALERT | ERR_FATAL;
962 goto out;
963 }
964 global.tune.server_sndbuf = atol(args[1]);
965 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200966 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200967 if (alertif_too_many_args(1, file, linenum, args, &err_code))
968 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
973 }
974 global.tune.pipesize = atol(args[1]);
975 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100976 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200977 if (alertif_too_many_args(1, file, linenum, args, &err_code))
978 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100979 if (*(args[1]) == 0) {
980 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
983 }
984 global.tune.cookie_len = atol(args[1]) + 1;
985 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200986 else if (!strcmp(args[0], "tune.http.logurilen")) {
987 if (alertif_too_many_args(1, file, linenum, args, &err_code))
988 goto out;
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 global.tune.requri_len = atol(args[1]) + 1;
995 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200996 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200997 if (alertif_too_many_args(1, file, linenum, args, &err_code))
998 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
Christopher Faulet50174f32017-06-21 16:31:35 +02001004 global.tune.max_http_hdr = atoi(args[1]);
1005 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
1006 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
1007 file, linenum, args[0]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001011 }
William Lallemandf3747832012-11-09 12:33:10 +01001012 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001013 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1014 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001015 if (*args[1]) {
1016 global.tune.comp_maxlevel = atoi(args[1]);
1017 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1018 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1019 file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023 } else {
1024 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1025 file, linenum, args[0]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001030 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1031 if (*args[1]) {
1032 global.tune.pattern_cache = atoi(args[1]);
1033 if (global.tune.pattern_cache < 0) {
1034 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1035 file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 } else {
1040 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1041 file, linenum, args[0]);
1042 err_code |= ERR_ALERT | ERR_FATAL;
1043 goto out;
1044 }
1045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001047 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001050 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT;
1052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 }
1054 if (*(args[1]) == 0) {
1055 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
1057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001059 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1060 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]);
1061 err_code |= ERR_WARN;
1062 goto out;
1063 }
1064
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 }
1066 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001067 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001070 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074 if (*(args[1]) == 0) {
1075 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001079 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1080 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]);
1081 err_code |= ERR_WARN;
1082 goto out;
1083 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 }
Simon Horman98637e52014-06-20 12:30:16 +09001085 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1087 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001088 global.external_check = 1;
1089 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001090 /* user/group name handling */
1091 else if (!strcmp(args[0], "user")) {
1092 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001093 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1094 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001095 if (global.uid != 0) {
1096 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001097 err_code |= ERR_ALERT;
1098 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001099 }
1100 errno = 0;
1101 ha_user = getpwnam(args[1]);
1102 if (ha_user != NULL) {
1103 global.uid = (int)ha_user->pw_uid;
1104 }
1105 else {
1106 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 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001108 }
1109 }
1110 else if (!strcmp(args[0], "group")) {
1111 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001112 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1113 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001114 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001115 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001116 err_code |= ERR_ALERT;
1117 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 errno = 0;
1120 ha_group = getgrnam(args[1]);
1121 if (ha_group != NULL) {
1122 global.gid = (int)ha_group->gr_gid;
1123 }
1124 else {
1125 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 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001127 }
1128 }
1129 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001131 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 if (*(args[1]) == 0) {
1134 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001139 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1140 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1141 file, linenum, args[0], LONGBITS, global.nbproc);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
1144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 }
Christopher Fauletbe0faa22017-08-29 15:37:10 +02001146 else if (!strcmp(args[0], "nbthread")) {
1147 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1148 goto out;
1149 if (*(args[1]) == 0) {
1150 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto out;
1153 }
1154 global.nbthread = atol(args[1]);
1155 if (global.nbthread < 1 || global.nbthread > LONGBITS) {
1156 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1157 file, linenum, args[0], LONGBITS, global.nbthread);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
1160 }
1161#ifndef USE_THREAD
1162 if (global.nbthread > 1) {
1163 Alert("HAProxy is not compiled with threads support, please check build options for USE_THREAD.\n");
1164 global.nbthread = 1;
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168#endif
1169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001171 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 if (global.maxconn != 0) {
1174 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001175 err_code |= ERR_ALERT;
1176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 }
1178 if (*(args[1]) == 0) {
1179 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 }
1183 global.maxconn = atol(args[1]);
1184#ifdef SYSTEM_MAXCONN
1185 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1186 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);
1187 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001188 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 }
1190#endif /* SYSTEM_MAXCONN */
1191 }
Emeric Brun850efd52014-01-29 12:24:34 +01001192 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001193 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1194 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001195 if (*(args[1]) == 0) {
1196 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200 if (strcmp(args[1],"none") == 0)
1201 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1202 else if (strcmp(args[1],"required") == 0)
1203 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1204 else {
1205 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
1208 }
1209 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001210 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001211 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1212 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001213 if (global.cps_lim != 0) {
1214 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1215 err_code |= ERR_ALERT;
1216 goto out;
1217 }
1218 if (*(args[1]) == 0) {
1219 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223 global.cps_lim = atol(args[1]);
1224 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001225 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001226 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1227 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001228 if (global.sps_lim != 0) {
1229 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1230 err_code |= ERR_ALERT;
1231 goto out;
1232 }
1233 if (*(args[1]) == 0) {
1234 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238 global.sps_lim = atol(args[1]);
1239 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001240 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001241 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1242 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001243 if (global.ssl_lim != 0) {
1244 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1245 err_code |= ERR_ALERT;
1246 goto out;
1247 }
1248 if (*(args[1]) == 0) {
1249 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253 global.ssl_lim = atol(args[1]);
1254 }
William Lallemandd85f9172012-11-09 17:05:39 +01001255 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001256 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1257 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 global.comp_rate_lim = atoi(args[1]) * 1024;
1264 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001265 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001266 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1267 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001268 if (global.maxpipes != 0) {
1269 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001270 err_code |= ERR_ALERT;
1271 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001272 }
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001277 }
1278 global.maxpipes = atol(args[1]);
1279 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001280 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001281 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1282 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001283 if (*(args[1]) == 0) {
1284 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
William Lallemande3a7d992012-11-20 11:25:20 +01001288 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001289 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001290 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001291 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1292 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001293 if (*(args[1]) == 0) {
1294 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
1298 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001299 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001300 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001304 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001305
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001307 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 if (global.rlimit_nofile != 0) {
1310 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001311 err_code |= ERR_ALERT;
1312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313 }
1314 if (*(args[1]) == 0) {
1315 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 }
1319 global.rlimit_nofile = atol(args[1]);
1320 }
1321 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001322 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 if (global.chroot != NULL) {
1325 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001326 err_code |= ERR_ALERT;
1327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 }
1329 if (*(args[1]) == 0) {
1330 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333 }
1334 global.chroot = strdup(args[1]);
1335 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001336 else if (!strcmp(args[0], "description")) {
1337 int i, len=0;
1338 char *d;
1339
1340 if (!*args[1]) {
1341 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1342 file, linenum, args[0]);
1343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
1345 }
1346
Willy Tarreau348acfe2014-04-14 15:00:39 +02001347 for (i = 1; *args[i]; i++)
1348 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001349
1350 if (global.desc)
1351 free(global.desc);
1352
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001353 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001354
Willy Tarreau348acfe2014-04-14 15:00:39 +02001355 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1356 for (i = 2; *args[i]; i++)
1357 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001358 }
1359 else if (!strcmp(args[0], "node")) {
1360 int i;
1361 char c;
1362
William Lallemand1a748ae2015-05-19 16:37:23 +02001363 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1364 goto out;
1365
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001366 for (i=0; args[1][i]; i++) {
1367 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001368 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1369 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001370 break;
1371 }
1372
1373 if (!i || args[1][i]) {
1374 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1375 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1376 file, linenum, args[0]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
1380
1381 if (global.node)
1382 free(global.node);
1383
1384 global.node = strdup(args[1]);
1385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001387 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 if (global.pidfile != NULL) {
1390 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT;
1392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 }
1394 if (*(args[1]) == 0) {
1395 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001396 err_code |= ERR_ALERT | ERR_FATAL;
1397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 }
1399 global.pidfile = strdup(args[1]);
1400 }
Emeric Bruned760922010-10-22 17:59:25 +02001401 else if (!strcmp(args[0], "unix-bind")) {
1402 int cur_arg = 1;
1403 while (*(args[cur_arg])) {
1404 if (!strcmp(args[cur_arg], "prefix")) {
1405 if (global.unix_bind.prefix != NULL) {
1406 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1407 err_code |= ERR_ALERT;
1408 cur_arg += 2;
1409 continue;
1410 }
1411
1412 if (*(args[cur_arg+1]) == 0) {
1413 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto out;
1416 }
1417 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1418 cur_arg += 2;
1419 continue;
1420 }
1421
1422 if (!strcmp(args[cur_arg], "mode")) {
1423
1424 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1425 cur_arg += 2;
1426 continue;
1427 }
1428
1429 if (!strcmp(args[cur_arg], "uid")) {
1430
1431 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1432 cur_arg += 2;
1433 continue;
1434 }
1435
1436 if (!strcmp(args[cur_arg], "gid")) {
1437
1438 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1439 cur_arg += 2;
1440 continue;
1441 }
1442
1443 if (!strcmp(args[cur_arg], "user")) {
1444 struct passwd *user;
1445
1446 user = getpwnam(args[cur_arg + 1]);
1447 if (!user) {
1448 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1449 file, linenum, args[0], args[cur_arg + 1 ]);
1450 err_code |= ERR_ALERT | ERR_FATAL;
1451 goto out;
1452 }
1453
1454 global.unix_bind.ux.uid = user->pw_uid;
1455 cur_arg += 2;
1456 continue;
1457 }
1458
1459 if (!strcmp(args[cur_arg], "group")) {
1460 struct group *group;
1461
1462 group = getgrnam(args[cur_arg + 1]);
1463 if (!group) {
1464 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1465 file, linenum, args[0], args[cur_arg + 1 ]);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
1468 }
1469
1470 global.unix_bind.ux.gid = group->gr_gid;
1471 cur_arg += 2;
1472 continue;
1473 }
1474
Willy Tarreaub48f9582011-09-05 01:17:06 +02001475 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001476 file, linenum, args[0]);
1477 err_code |= ERR_ALERT | ERR_FATAL;
1478 goto out;
1479 }
1480 }
William Lallemand0f99e342011-10-12 17:50:54 +02001481 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1482 /* delete previous herited or defined syslog servers */
1483 struct logsrv *back;
1484 struct logsrv *tmp;
1485
1486 if (*(args[1]) != 0) {
1487 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1488 err_code |= ERR_ALERT | ERR_FATAL;
1489 goto out;
1490 }
1491
1492 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1493 LIST_DEL(&tmp->list);
1494 free(tmp);
1495 }
1496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001498 struct sockaddr_storage *sk;
1499 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001500 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001501 int arg = 0;
1502 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001503
William Lallemand1a748ae2015-05-19 16:37:23 +02001504 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1505 goto out;
1506
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 if (*(args[1]) == 0 || *(args[2]) == 0) {
1508 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511 }
William Lallemand0f99e342011-10-12 17:50:54 +02001512
Vincent Bernat02779b62016-04-03 13:48:43 +02001513 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001514
Willy Tarreau18324f52014-06-27 18:10:07 +02001515 /* just after the address, a length may be specified */
1516 if (strcmp(args[arg+2], "len") == 0) {
1517 len = atoi(args[arg+3]);
1518 if (len < 80 || len > 65535) {
1519 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1520 file, linenum, args[arg+3]);
1521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto out;
1523 }
1524 logsrv->maxlen = len;
1525
1526 /* skip these two args */
1527 arg += 2;
1528 }
1529 else
1530 logsrv->maxlen = MAX_SYSLOG_LEN;
1531
Christopher Faulet084aa962017-08-29 16:54:41 +02001532 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001533 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001534
Dragan Dosen1322d092015-09-22 16:05:32 +02001535 /* after the length, a format may be specified */
1536 if (strcmp(args[arg+2], "format") == 0) {
1537 logsrv->format = get_log_format(args[arg+3]);
1538 if (logsrv->format < 0) {
1539 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1540 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001541 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001542 goto out;
1543 }
1544
1545 /* skip these two args */
1546 arg += 2;
1547 }
1548
David Carlier97880bb2016-04-08 10:35:26 +01001549 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1550 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001551 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001552 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001553
Willy Tarreau18324f52014-06-27 18:10:07 +02001554 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001555 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001556 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001557 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001558 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 }
1560
William Lallemand0f99e342011-10-12 17:50:54 +02001561 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001562 if (*(args[arg+3])) {
1563 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001564 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001565 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001566 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001567 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 }
1569 }
1570
William Lallemand0f99e342011-10-12 17:50:54 +02001571 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001572 if (*(args[arg+4])) {
1573 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001574 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001575 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001577 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001578 }
1579 }
1580
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001581 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001582 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001583 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001584 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001585 free(logsrv);
1586 goto out;
1587 }
1588 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001589
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001590 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001591 if (port1 != port2) {
1592 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1593 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001594 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001595 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001596 goto out;
1597 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001598
William Lallemand0f99e342011-10-12 17:50:54 +02001599 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001600 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001601 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603
William Lallemand0f99e342011-10-12 17:50:54 +02001604 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001605 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001606 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1607 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001608
1609 if (global.log_send_hostname != NULL) {
1610 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1611 err_code |= ERR_ALERT;
1612 goto out;
1613 }
1614
1615 if (*(args[1]))
1616 name = args[1];
1617 else
1618 name = hostname;
1619
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001620 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001621 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001622 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001623 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1624 if (global.server_state_base != NULL) {
1625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1626 err_code |= ERR_ALERT;
1627 goto out;
1628 }
1629
1630 if (!*(args[1])) {
1631 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1632 err_code |= ERR_FATAL;
1633 goto out;
1634 }
1635
1636 global.server_state_base = strdup(args[1]);
1637 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001638 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1639 if (global.server_state_file != NULL) {
1640 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1641 err_code |= ERR_ALERT;
1642 goto out;
1643 }
1644
1645 if (!*(args[1])) {
1646 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1647 err_code |= ERR_FATAL;
1648 goto out;
1649 }
1650
1651 global.server_state_file = strdup(args[1]);
1652 }
Kevinm48936af2010-12-22 16:08:21 +00001653 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001654 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1655 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001656 if (*(args[1]) == 0) {
1657 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
1660 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001661 chunk_destroy(&global.log_tag);
1662 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001663 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001664 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001665 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1666 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001667 if (global.spread_checks != 0) {
1668 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001669 err_code |= ERR_ALERT;
1670 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001671 }
1672 if (*(args[1]) == 0) {
1673 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001676 }
1677 global.spread_checks = atol(args[1]);
1678 if (global.spread_checks < 0 || global.spread_checks > 50) {
1679 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001680 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001683 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1684 const char *err;
1685 unsigned int val;
1686
William Lallemand1a748ae2015-05-19 16:37:23 +02001687 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1688 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001689 if (*(args[1]) == 0) {
1690 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
1693 }
1694
1695 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1696 if (err) {
1697 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1698 err_code |= ERR_ALERT | ERR_FATAL;
1699 }
1700 global.max_spread_checks = val;
1701 if (global.max_spread_checks < 0) {
1702 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1703 err_code |= ERR_ALERT | ERR_FATAL;
1704 }
1705 }
Christopher Faulet62519022017-10-16 15:49:32 +02001706 else if (strcmp(args[0], "cpu-map") == 0) {
1707 /* map a process list to a CPU set */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001708#ifdef USE_CPU_AFFINITY
Christopher Faulet5ab51772017-11-22 11:21:58 +01001709 unsigned long proc = 0, cpus;
Christopher Faulet26028f62017-11-22 15:01:51 +01001710 int i, n, autoinc;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001711
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001712 if (!*args[1] || !*args[2]) {
1713 Alert("parsing [%s:%d] : %s expects a process number "
1714 " ('all', 'odd', 'even', a number from 1 to %d or a range), "
Christopher Faulet62519022017-10-16 15:49:32 +02001715 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001716 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
1719 }
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001720
Christopher Faulet26028f62017-11-22 15:01:51 +01001721 if (parse_process_number(args[1], &proc, &autoinc, &errmsg)) {
Christopher Faulet5ab51772017-11-22 11:21:58 +01001722 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
Christopher Faulet1dcb9cb2017-11-22 10:24:40 +01001723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726
Christopher Faulet62519022017-10-16 15:49:32 +02001727 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
1728 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001731 }
Christopher Faulet26028f62017-11-22 15:01:51 +01001732
1733 if (autoinc && my_popcountl(proc) != my_popcountl(cpus)) {
1734 Alert("parsing [%s:%d] : %s : PROC range and CPU sets must have the same size to be auto-assigned\n",
1735 file, linenum, args[0]);
1736 err_code |= ERR_ALERT | ERR_FATAL;
1737 goto out;
1738 }
1739 for (i = n = 0; i < LONGBITS; i++) {
1740 if (proc & (1UL << i)) {
1741 if (autoinc) {
1742 n += my_ffsl(cpus >> n);
1743 global.cpu_map[i] = (1UL << (n-1));
1744 }
1745 else
1746 global.cpu_map[i] = cpus;
1747 }
1748 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001749#else
Christopher Faulet62519022017-10-16 15:49:32 +02001750 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1751 file, linenum, args[0]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Christopher Faulet62519022017-10-16 15:49:32 +02001754#endif /* ! USE_CPU_AFFINITY */
1755 }
1756 else if (strcmp(args[0], "thread-map") == 0) {
1757 /* map a thread list to a CPU set */
1758#ifdef USE_CPU_AFFINITY
1759#ifdef USE_THREAD
Christopher Faulet5ab51772017-11-22 11:21:58 +01001760 unsigned long proc = 0, thread = 0, cpus;
Christopher Faulet62519022017-10-16 15:49:32 +02001761 int i, j;
1762
Christopher Faulet5ab51772017-11-22 11:21:58 +01001763 if (!*args[1] || !*args[2] || !*args[3]) {
Christopher Faulet62519022017-10-16 15:49:32 +02001764 Alert("parsing [%s:%d]: %s expects a process number "
1765 "('all', 'odd', 'even', or a number from 1 to %d), "
1766 " followed by a thread number using the same format, "
1767 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
1768 file, linenum, args[0], LONGBITS, LONGBITS - 1);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
Christopher Faulet5ab51772017-11-22 11:21:58 +01001772
Christopher Faulet26028f62017-11-22 15:01:51 +01001773 if (parse_process_number(args[1], &proc, NULL, &errmsg)) {
Christopher Faulet5ab51772017-11-22 11:21:58 +01001774 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
1777 }
Christopher Faulet26028f62017-11-22 15:01:51 +01001778 if (parse_process_number(args[2], &thread, NULL, &errmsg)) {
Christopher Faulet5ab51772017-11-22 11:21:58 +01001779 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
Christopher Faulet62519022017-10-16 15:49:32 +02001783 if (parse_cpu_set((const char **)args+3, &cpus, &errmsg)) {
1784 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
Christopher Faulet5ab51772017-11-22 11:21:58 +01001788
Christopher Faulet62519022017-10-16 15:49:32 +02001789 for (i = 0; i < LONGBITS; i++)
1790 if (proc & (1UL << i)) {
1791 for (j = 0; j < LONGBITS; j++)
1792 if (thread & (1UL << j))
1793 global.thread_map[i][j] = cpus;
1794 }
1795#else
1796 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_THREAD.\n",
1797 file, linenum, args[0]);
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800#endif /* ! USE_THREAD*/
1801#else
1802 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1803 file, linenum, args[0]);
1804 err_code |= ERR_ALERT | ERR_FATAL;
1805 goto out;
1806#endif /* ! USE_CPU_AFFINITY */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001807 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001808 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1809 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1810 goto out;
1811
1812 if (*(args[2]) == 0) {
1813 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817
1818 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1819 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1820 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
1823 }
1824 }
1825 else if (!strcmp(args[0], "unsetenv")) {
1826 int arg;
1827
1828 if (*(args[1]) == 0) {
1829 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1830 err_code |= ERR_ALERT | ERR_FATAL;
1831 goto out;
1832 }
1833
1834 for (arg = 1; *args[arg]; arg++) {
1835 if (unsetenv(args[arg]) != 0) {
1836 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840 }
1841 }
1842 else if (!strcmp(args[0], "resetenv")) {
1843 extern char **environ;
1844 char **env = environ;
1845
1846 /* args contain variable names to keep, one per argument */
1847 while (*env) {
1848 int arg;
1849
1850 /* look for current variable in among all those we want to keep */
1851 for (arg = 1; *args[arg]; arg++) {
1852 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1853 (*env)[strlen(args[arg])] == '=')
1854 break;
1855 }
1856
1857 /* delete this variable */
1858 if (!*args[arg]) {
1859 char *delim = strchr(*env, '=');
1860
1861 if (!delim || delim - *env >= trash.size) {
1862 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1863 err_code |= ERR_ALERT | ERR_FATAL;
1864 goto out;
1865 }
1866
1867 memcpy(trash.str, *env, delim - *env);
1868 trash.str[delim - *env] = 0;
1869
1870 if (unsetenv(trash.str) != 0) {
1871 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1872 err_code |= ERR_ALERT | ERR_FATAL;
1873 goto out;
1874 }
1875 }
1876 else
1877 env++;
1878 }
1879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001881 struct cfg_kw_list *kwl;
1882 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001883 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001884
1885 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1886 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1887 if (kwl->kw[index].section != CFG_GLOBAL)
1888 continue;
1889 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001890 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001891 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001892 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001893 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001894 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001895 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001896 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001897 err_code |= ERR_WARN;
1898 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001899 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001900 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001901 }
1902 }
1903 }
1904
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001908
Willy Tarreau058e9072009-07-20 09:30:05 +02001909 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001910 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001911 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912}
1913
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001914void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001916 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 defproxy.mode = PR_MODE_TCP;
1918 defproxy.state = PR_STNEW;
1919 defproxy.maxconn = cfg_maxpconn;
1920 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001921 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001922 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001923
Simon Horman66183002013-02-23 10:16:43 +09001924 defproxy.defsrv.check.inter = DEF_CHKINTR;
1925 defproxy.defsrv.check.fastinter = 0;
1926 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001927 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1928 defproxy.defsrv.agent.fastinter = 0;
1929 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001930 defproxy.defsrv.check.rise = DEF_RISETIME;
1931 defproxy.defsrv.check.fall = DEF_FALLTIME;
1932 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1933 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001934 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001935 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001936 defproxy.defsrv.maxqueue = 0;
1937 defproxy.defsrv.minconn = 0;
1938 defproxy.defsrv.maxconn = 0;
1939 defproxy.defsrv.slowstart = 0;
1940 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1941 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1942 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001943
1944 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001945 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946}
1947
Willy Tarreauade5ec42010-01-28 19:33:49 +01001948
Willy Tarreau63af98d2014-05-18 08:11:41 +02001949/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1950 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1951 * ERR_FATAL in case of error.
1952 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001953static int create_cond_regex_rule(const char *file, int line,
1954 struct proxy *px, int dir, int action, int flags,
1955 const char *cmd, const char *reg, const char *repl,
1956 const char **cond_start)
1957{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001958 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001959 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001960 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001961 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001962 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001963 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001964 int cs;
1965 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001966
1967 if (px == &defproxy) {
1968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001969 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001970 goto err;
1971 }
1972
1973 if (*reg == 0) {
1974 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001975 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001976 goto err;
1977 }
1978
Christopher Faulet898566e2016-10-26 11:06:28 +02001979 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001980 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001981
Willy Tarreau5321c422010-01-28 20:35:13 +01001982 if (cond_start &&
1983 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02001984 if ((cond = build_acl_cond(file, line, &px->acl, px, cond_start, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001985 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1986 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001987 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001988 goto err;
1989 }
1990 }
1991 else if (cond_start && **cond_start) {
1992 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1993 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001994 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001995 goto err;
1996 }
1997
Willy Tarreau63af98d2014-05-18 08:11:41 +02001998 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001999 (dir == SMP_OPT_DIR_REQ) ?
2000 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2001 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2002 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002003
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002004 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002005 if (!preg) {
2006 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002007 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002008 goto err;
2009 }
2010
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002011 cs = !(flags & REG_ICASE);
2012 cap = !(flags & REG_NOSUB);
2013 error = NULL;
2014 if (!regex_comp(reg, preg, cs, cap, &error)) {
2015 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2016 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002017 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002018 goto err;
2019 }
2020
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002021 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002022 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002023 if (repl && err) {
2024 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2025 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002026 ret_code |= ERR_ALERT | ERR_FATAL;
2027 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002028 }
2029
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002030 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002031 ret_code |= ERR_WARN;
2032
2033 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002034
Willy Tarreau63af98d2014-05-18 08:11:41 +02002035 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002036 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002037 err:
2038 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002039 free(errmsg);
2040 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002041}
2042
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043/*
William Lallemand51097192015-04-14 16:35:22 +02002044 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002045 * Returns the error code, 0 if OK, or any combination of :
2046 * - ERR_ABORT: must abort ASAP
2047 * - ERR_FATAL: we can continue parsing but not start the service
2048 * - ERR_WARN: a warning has been emitted
2049 * - ERR_ALERT: an alert has been emitted
2050 * Only the two first ones can stop processing, the two others are just
2051 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002053int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2054{
2055 static struct peers *curpeers = NULL;
2056 struct peer *newpeer = NULL;
2057 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002058 struct bind_conf *bind_conf;
2059 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002060 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002061 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002062
2063 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002064 if (!*args[1]) {
2065 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002066 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002067 goto out;
2068 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002069
William Lallemand6e62fb62015-04-28 16:55:23 +02002070 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2071 goto out;
2072
Emeric Brun32da3c42010-09-23 18:39:19 +02002073 err = invalid_char(args[1]);
2074 if (err) {
2075 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2076 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002077 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002078 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002079 }
2080
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002081 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002082 /*
2083 * If there are two proxies with the same name only following
2084 * combinations are allowed:
2085 */
2086 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002087 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 +02002088 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002089 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002090 }
2091 }
2092
Vincent Bernat02779b62016-04-03 13:48:43 +02002093 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002094 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2095 err_code |= ERR_ALERT | ERR_ABORT;
2096 goto out;
2097 }
2098
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002099 curpeers->next = cfg_peers;
2100 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002101 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002102 curpeers->conf.line = linenum;
2103 curpeers->last_change = now.tv_sec;
2104 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002105 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002106 }
2107 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002108 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002109 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002110 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002111
2112 if (!*args[2]) {
2113 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2114 file, linenum, args[0]);
2115 err_code |= ERR_ALERT | ERR_FATAL;
2116 goto out;
2117 }
2118
2119 err = invalid_char(args[1]);
2120 if (err) {
2121 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2122 file, linenum, *err, args[1]);
2123 err_code |= ERR_ALERT | ERR_FATAL;
2124 goto out;
2125 }
2126
Vincent Bernat02779b62016-04-03 13:48:43 +02002127 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2129 err_code |= ERR_ALERT | ERR_ABORT;
2130 goto out;
2131 }
2132
2133 /* the peers are linked backwards first */
2134 curpeers->count++;
2135 newpeer->next = curpeers->remote;
2136 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002137 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002138 newpeer->conf.line = linenum;
2139
2140 newpeer->last_change = now.tv_sec;
2141 newpeer->id = strdup(args[1]);
2142
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002143 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002144 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002145 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002148 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002149
2150 proto = protocol_by_family(sk->ss_family);
2151 if (!proto || !proto->connect) {
2152 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2153 file, linenum, args[0], args[1]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002157
2158 if (port1 != port2) {
2159 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2160 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
2163 }
2164
Willy Tarreau2aa38802013-02-20 19:20:59 +01002165 if (!port1) {
2166 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2167 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002171
Emeric Brun32da3c42010-09-23 18:39:19 +02002172 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002173 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002174 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002175 newpeer->sock_init_arg = NULL;
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002176 HA_SPIN_INIT(&newpeer->lock);
Willy Tarreau26d8c592012-05-07 18:12:14 +02002177
Emeric Brun32da3c42010-09-23 18:39:19 +02002178 if (strcmp(newpeer->id, localpeer) == 0) {
2179 /* Current is local peer, it define a frontend */
2180 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002181 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002182
2183 if (!curpeers->peers_fe) {
2184 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2185 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2186 err_code |= ERR_ALERT | ERR_ABORT;
2187 goto out;
2188 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002189
Willy Tarreau237250c2011-07-29 01:49:03 +02002190 init_new_proxy(curpeers->peers_fe);
2191 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002192 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002193 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2194 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002195 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002196
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002197 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002198
Willy Tarreau902636f2013-03-10 19:44:48 +01002199 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2200 if (errmsg && *errmsg) {
2201 indent_msg(&errmsg, 2);
2202 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002203 }
2204 else
2205 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2206 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002207 err_code |= ERR_FATAL;
2208 goto out;
2209 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002210
2211 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002212 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002213 l->maxconn = curpeers->peers_fe->maxconn;
2214 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002215 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002216 l->analysers |= curpeers->peers_fe->fe_req_ana;
2217 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002218 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2219 global.maxsock += l->maxconn;
2220 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002221 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002222 else {
2223 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2224 file, linenum, args[0], args[1],
2225 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2226 err_code |= ERR_FATAL;
2227 goto out;
2228 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002229 }
2230 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002231 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2232 curpeers->state = PR_STSTOPPED;
2233 }
2234 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2235 curpeers->state = PR_STNEW;
2236 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002237 else if (*args[0] != 0) {
2238 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242
2243out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002244 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002245 return err_code;
2246}
2247
Baptiste Assmann325137d2015-04-13 23:40:55 +02002248/*
2249 * Parse a <resolvers> section.
2250 * Returns the error code, 0 if OK, or any combination of :
2251 * - ERR_ABORT: must abort ASAP
2252 * - ERR_FATAL: we can continue parsing but not start the service
2253 * - ERR_WARN: a warning has been emitted
2254 * - ERR_ALERT: an alert has been emitted
2255 * Only the two first ones can stop processing, the two others are just
2256 * indicators.
2257 */
2258int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2259{
2260 static struct dns_resolvers *curr_resolvers = NULL;
2261 struct dns_nameserver *newnameserver = NULL;
2262 const char *err;
2263 int err_code = 0;
2264 char *errmsg = NULL;
2265
2266 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2267 if (!*args[1]) {
2268 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2269 err_code |= ERR_ALERT | ERR_ABORT;
2270 goto out;
2271 }
2272
2273 err = invalid_char(args[1]);
2274 if (err) {
2275 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2276 file, linenum, *err, args[0], args[1]);
2277 err_code |= ERR_ALERT | ERR_ABORT;
2278 goto out;
2279 }
2280
2281 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2282 /* Error if two resolvers owns the same name */
2283 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2284 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2285 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2286 err_code |= ERR_ALERT | ERR_ABORT;
2287 }
2288 }
2289
Vincent Bernat02779b62016-04-03 13:48:43 +02002290 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002291 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2292 err_code |= ERR_ALERT | ERR_ABORT;
2293 goto out;
2294 }
2295
2296 /* default values */
2297 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2298 curr_resolvers->conf.file = strdup(file);
2299 curr_resolvers->conf.line = linenum;
2300 curr_resolvers->id = strdup(args[1]);
2301 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002302 /* default maximum response size */
2303 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002304 /* default hold period for nx, other, refuse and timeout is 30s */
2305 curr_resolvers->hold.nx = 30000;
2306 curr_resolvers->hold.other = 30000;
2307 curr_resolvers->hold.refused = 30000;
2308 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002309 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002310 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002311 curr_resolvers->hold.valid = 10000;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002312 curr_resolvers->timeout.resolve = 1000;
2313 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002314 curr_resolvers->resolve_retries = 3;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002315 curr_resolvers->nb_nameservers = 0;
2316 LIST_INIT(&curr_resolvers->nameservers);
2317 LIST_INIT(&curr_resolvers->resolutions.curr);
2318 LIST_INIT(&curr_resolvers->resolutions.wait);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002319 HA_SPIN_INIT(&curr_resolvers->lock);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002320 }
2321 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2322 struct sockaddr_storage *sk;
2323 int port1, port2;
2324 struct protocol *proto;
2325
2326 if (!*args[2]) {
2327 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2328 file, linenum, args[0]);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332
2333 err = invalid_char(args[1]);
2334 if (err) {
2335 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2336 file, linenum, *err, args[1]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
Christopher Faulet67957bd2017-09-27 11:00:59 +02002341 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002342 /* Error if two resolvers owns the same name */
2343 if (strcmp(newnameserver->id, args[1]) == 0) {
2344 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2345 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 }
2348 }
2349
Vincent Bernat02779b62016-04-03 13:48:43 +02002350 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002351 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2352 err_code |= ERR_ALERT | ERR_ABORT;
2353 goto out;
2354 }
2355
2356 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002357 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002358 newnameserver->resolvers = curr_resolvers;
2359 newnameserver->conf.file = strdup(file);
2360 newnameserver->conf.line = linenum;
2361 newnameserver->id = strdup(args[1]);
2362
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002363 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002364 if (!sk) {
2365 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369
2370 proto = protocol_by_family(sk->ss_family);
2371 if (!proto || !proto->connect) {
2372 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2373 file, linenum, args[0], args[1]);
2374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
2376 }
2377
2378 if (port1 != port2) {
2379 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2380 file, linenum, args[0], args[1], args[2]);
2381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
2383 }
2384
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002385 if (!port1 && !port2) {
2386 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2387 file, linenum, args[0], args[1]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
Baptiste Assmann325137d2015-04-13 23:40:55 +02002392 newnameserver->addr = *sk;
2393 }
2394 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2395 const char *res;
2396 unsigned int time;
2397
2398 if (!*args[2]) {
2399 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2400 file, linenum, args[0]);
2401 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
2404 }
2405 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2406 if (res) {
2407 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2408 file, linenum, *res, args[0]);
2409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
2411 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002412 if (strcmp(args[1], "nx") == 0)
2413 curr_resolvers->hold.nx = time;
2414 else if (strcmp(args[1], "other") == 0)
2415 curr_resolvers->hold.other = time;
2416 else if (strcmp(args[1], "refused") == 0)
2417 curr_resolvers->hold.refused = time;
2418 else if (strcmp(args[1], "timeout") == 0)
2419 curr_resolvers->hold.timeout = time;
2420 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002421 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002422 else if (strcmp(args[1], "obsolete") == 0)
2423 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002424 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002425 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002426 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
2429 }
2430
2431 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002432 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002433 int i = 0;
2434
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002435 if (!*args[1]) {
2436 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2437 file, linenum, args[0]);
2438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
2440 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002441
2442 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002443 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2444 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2445 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
2450 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002451 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002452 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002453 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2454 file, linenum, args[0]);
2455 err_code |= ERR_WARN;
2456 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002457 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002458 else if (strcmp(args[0], "resolve_retries") == 0) {
2459 if (!*args[1]) {
2460 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2461 file, linenum, args[0]);
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465 curr_resolvers->resolve_retries = atoi(args[1]);
2466 }
2467 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002468 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002469 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002470 file, linenum, args[0]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002474 else if (strcmp(args[1], "retry") == 0 ||
2475 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002476 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002477 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002478
2479 if (!*args[2]) {
2480 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2481 file, linenum, args[0], args[1]);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002485 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002486 if (res) {
2487 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2488 file, linenum, *res, args[0], args[1]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002492 if (args[1][2] == 't')
2493 curr_resolvers->timeout.retry = tout;
2494 else
2495 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002496 }
2497 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002498 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002499 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002503 } /* neither "nameserver" nor "resolvers" */
2504 else if (*args[0] != 0) {
2505 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
2508 }
2509
2510 out:
2511 free(errmsg);
2512 return err_code;
2513}
Simon Horman0d16a402015-01-30 11:22:58 +09002514
2515/*
William Lallemand51097192015-04-14 16:35:22 +02002516 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002517 * Returns the error code, 0 if OK, or any combination of :
2518 * - ERR_ABORT: must abort ASAP
2519 * - ERR_FATAL: we can continue parsing but not start the service
2520 * - ERR_WARN: a warning has been emitted
2521 * - ERR_ALERT: an alert has been emitted
2522 * Only the two first ones can stop processing, the two others are just
2523 * indicators.
2524 */
2525int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2526{
2527 static struct mailers *curmailers = NULL;
2528 struct mailer *newmailer = NULL;
2529 const char *err;
2530 int err_code = 0;
2531 char *errmsg = NULL;
2532
2533 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2534 if (!*args[1]) {
2535 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2536 err_code |= ERR_ALERT | ERR_ABORT;
2537 goto out;
2538 }
2539
2540 err = invalid_char(args[1]);
2541 if (err) {
2542 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2543 file, linenum, *err, args[0], args[1]);
2544 err_code |= ERR_ALERT | ERR_ABORT;
2545 goto out;
2546 }
2547
2548 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2549 /*
2550 * If there are two proxies with the same name only following
2551 * combinations are allowed:
2552 */
2553 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002554 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 +09002555 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002557 }
2558 }
2559
Vincent Bernat02779b62016-04-03 13:48:43 +02002560 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002561 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2562 err_code |= ERR_ALERT | ERR_ABORT;
2563 goto out;
2564 }
2565
2566 curmailers->next = mailers;
2567 mailers = curmailers;
2568 curmailers->conf.file = strdup(file);
2569 curmailers->conf.line = linenum;
2570 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002571 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2572 * But need enough time so that timeouts don't occur
2573 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002574 }
2575 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2576 struct sockaddr_storage *sk;
2577 int port1, port2;
2578 struct protocol *proto;
2579
2580 if (!*args[2]) {
2581 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2582 file, linenum, args[0]);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
2585 }
2586
2587 err = invalid_char(args[1]);
2588 if (err) {
2589 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2590 file, linenum, *err, args[1]);
2591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
2593 }
2594
Vincent Bernat02779b62016-04-03 13:48:43 +02002595 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002596 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2597 err_code |= ERR_ALERT | ERR_ABORT;
2598 goto out;
2599 }
2600
2601 /* the mailers are linked backwards first */
2602 curmailers->count++;
2603 newmailer->next = curmailers->mailer_list;
2604 curmailers->mailer_list = newmailer;
2605 newmailer->mailers = curmailers;
2606 newmailer->conf.file = strdup(file);
2607 newmailer->conf.line = linenum;
2608
2609 newmailer->id = strdup(args[1]);
2610
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002611 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002612 if (!sk) {
2613 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617
2618 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002619 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2620 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002621 file, linenum, args[0], args[1]);
2622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
2624 }
2625
2626 if (port1 != port2) {
2627 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2628 file, linenum, args[0], args[1], args[2]);
2629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
2631 }
2632
2633 if (!port1) {
2634 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2635 file, linenum, args[0], args[1], args[2]);
2636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
2638 }
2639
2640 newmailer->addr = *sk;
2641 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002642 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002643 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002644 }
2645 else if (strcmp(args[0], "timeout") == 0) {
2646 if (!*args[1]) {
2647 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2648 file, linenum, args[0]);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651 }
2652 else if (strcmp(args[1], "mail") == 0) {
2653 const char *res;
2654 unsigned int timeout_mail;
2655 if (!*args[2]) {
2656 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2657 file, linenum, args[0], args[1]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2662 if (res) {
2663 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2664 file, linenum, *res, args[0]);
2665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
2667 }
2668 if (timeout_mail <= 0) {
2669 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673 curmailers->timeout.mail = timeout_mail;
2674 } else {
2675 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2676 file, linenum, args[0], args[1]);
2677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680 }
Simon Horman0d16a402015-01-30 11:22:58 +09002681 else if (*args[0] != 0) {
2682 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686
2687out:
2688 free(errmsg);
2689 return err_code;
2690}
2691
Simon Horman9dc49962015-01-30 11:22:59 +09002692static void free_email_alert(struct proxy *p)
2693{
2694 free(p->email_alert.mailers.name);
2695 p->email_alert.mailers.name = NULL;
2696 free(p->email_alert.from);
2697 p->email_alert.from = NULL;
2698 free(p->email_alert.to);
2699 p->email_alert.to = NULL;
2700 free(p->email_alert.myhostname);
2701 p->email_alert.myhostname = NULL;
2702}
2703
Willy Tarreau3842f002009-06-14 11:39:52 +02002704int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705{
2706 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002707 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002708 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002709 int rc;
2710 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002711 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002712 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002713 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002714 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002715 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 if (!strcmp(args[0], "listen"))
2718 rc = PR_CAP_LISTEN;
2719 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002720 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002721 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002722 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002723 else
2724 rc = PR_CAP_NONE;
2725
2726 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 if (!*args[1]) {
2728 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002729 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002731 err_code |= ERR_ALERT | ERR_ABORT;
2732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002734
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002735 err = invalid_char(args[1]);
2736 if (err) {
2737 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2738 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002740 }
2741
Willy Tarreau8f50b682015-05-26 11:45:02 +02002742 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2743 if (curproxy) {
2744 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2745 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2746 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002747 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002748 }
2749
Vincent Bernat02779b62016-04-03 13:48:43 +02002750 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002752 err_code |= ERR_ALERT | ERR_ABORT;
2753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002755
Willy Tarreau97cb7802010-01-03 20:23:58 +01002756 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 curproxy->next = proxy;
2758 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002759 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2760 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002761 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002763 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002764 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765
William Lallemand6e62fb62015-04-28 16:55:23 +02002766 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2767 if (curproxy->cap & PR_CAP_FE)
2768 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
2771
2772 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002773 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002774 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002775
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002778 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002779 curproxy->no_options = defproxy.no_options;
2780 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002781 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002782 curproxy->except_net = defproxy.except_net;
2783 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002784 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002785 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002787 if (defproxy.fwdfor_hdr_len) {
2788 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2789 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2790 }
2791
Willy Tarreaub86db342009-11-30 11:50:16 +01002792 if (defproxy.orgto_hdr_len) {
2793 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2794 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2795 }
2796
Mark Lamourinec2247f02012-01-04 13:02:01 -05002797 if (defproxy.server_id_hdr_len) {
2798 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2799 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2800 }
2801
Willy Tarreau977b8e42006-12-29 14:19:17 +01002802 if (curproxy->cap & PR_CAP_FE) {
2803 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002804 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002805 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002806
2807 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002808 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2809 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002810
2811 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813
Willy Tarreau977b8e42006-12-29 14:19:17 +01002814 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002815 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002816 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002817 curproxy->fullconn = defproxy.fullconn;
2818 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002819 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002820 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002822 if (defproxy.check_req) {
2823 curproxy->check_req = calloc(1, defproxy.check_len);
2824 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2825 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002826 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002828 if (defproxy.expect_str) {
2829 curproxy->expect_str = strdup(defproxy.expect_str);
2830 if (defproxy.expect_regex) {
2831 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002832 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2833 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002834 }
2835 }
2836
Willy Tarreau67402132012-05-31 20:40:20 +02002837 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002838 if (defproxy.cookie_name)
2839 curproxy->cookie_name = strdup(defproxy.cookie_name);
2840 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002841
2842 if (defproxy.dyncookie_key)
2843 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002844 if (defproxy.cookie_domain)
2845 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002846
Willy Tarreau31936852010-10-06 16:59:56 +02002847 if (defproxy.cookie_maxidle)
2848 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2849
2850 if (defproxy.cookie_maxlife)
2851 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2852
Emeric Brun647caf12009-06-30 17:57:00 +02002853 if (defproxy.rdp_cookie_name)
2854 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2855 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2856
Willy Tarreau01732802007-11-01 22:48:15 +01002857 if (defproxy.url_param_name)
2858 curproxy->url_param_name = strdup(defproxy.url_param_name);
2859 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002860
Benoitaffb4812009-03-25 13:02:10 +01002861 if (defproxy.hh_name)
2862 curproxy->hh_name = strdup(defproxy.hh_name);
2863 curproxy->hh_len = defproxy.hh_len;
2864 curproxy->hh_match_domain = defproxy.hh_match_domain;
2865
Willy Tarreauef9a3602012-12-08 22:29:20 +01002866 if (defproxy.conn_src.iface_name)
2867 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2868 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002869 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002870#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002871 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002872#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002873 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002874 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002876 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002877 if (defproxy.capture_name)
2878 curproxy->capture_name = strdup(defproxy.capture_name);
2879 curproxy->capture_namelen = defproxy.capture_namelen;
2880 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882
Willy Tarreau977b8e42006-12-29 14:19:17 +01002883 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002884 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002885 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002886 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002887 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002888 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889 curproxy->mon_net = defproxy.mon_net;
2890 curproxy->mon_mask = defproxy.mon_mask;
2891 if (defproxy.monitor_uri)
2892 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2893 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002894 if (defproxy.defbe.name)
2895 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002896
2897 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002898 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2899 if (curproxy->conf.logformat_string &&
2900 curproxy->conf.logformat_string != default_http_log_format &&
2901 curproxy->conf.logformat_string != default_tcp_log_format &&
2902 curproxy->conf.logformat_string != clf_http_log_format)
2903 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2904
2905 if (defproxy.conf.lfs_file) {
2906 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2907 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2908 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002909
2910 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2911 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2912 if (curproxy->conf.logformat_sd_string &&
2913 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2914 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2915
2916 if (defproxy.conf.lfsd_file) {
2917 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2918 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2919 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920 }
2921
2922 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002923 curproxy->timeout.connect = defproxy.timeout.connect;
2924 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002925 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002926 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002927 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002928 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002929 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002930 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002931 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002932 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002933 }
2934
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002936 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002937
2938 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002939 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002940 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002941 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002942 LIST_INIT(&node->list);
2943 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2944 }
2945
Willy Tarreau62a61232013-04-12 18:13:46 +02002946 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2947 if (curproxy->conf.uniqueid_format_string)
2948 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2949
Dragan Dosen43885c72015-10-01 13:18:13 +02002950 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002951
Willy Tarreau62a61232013-04-12 18:13:46 +02002952 if (defproxy.conf.uif_file) {
2953 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2954 curproxy->conf.uif_line = defproxy.conf.uif_line;
2955 }
William Lallemanda73203e2012-03-12 12:48:57 +01002956
2957 /* copy default header unique id */
2958 if (defproxy.header_unique_id)
2959 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2960
William Lallemand82fe75c2012-10-23 10:25:10 +02002961 /* default compression options */
2962 if (defproxy.comp != NULL) {
2963 curproxy->comp = calloc(1, sizeof(struct comp));
2964 curproxy->comp->algos = defproxy.comp->algos;
2965 curproxy->comp->types = defproxy.comp->types;
2966 }
2967
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002969 curproxy->conf.used_listener_id = EB_ROOT;
2970 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002971
Simon Horman98637e52014-06-20 12:30:16 +09002972 if (defproxy.check_path)
2973 curproxy->check_path = strdup(defproxy.check_path);
2974 if (defproxy.check_command)
2975 curproxy->check_command = strdup(defproxy.check_command);
2976
Simon Horman9dc49962015-01-30 11:22:59 +09002977 if (defproxy.email_alert.mailers.name)
2978 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2979 if (defproxy.email_alert.from)
2980 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2981 if (defproxy.email_alert.to)
2982 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2983 if (defproxy.email_alert.myhostname)
2984 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002985 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002986 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002987
Willy Tarreau93893792009-07-23 13:19:11 +02002988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 }
2990 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2991 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002992 /* FIXME-20070101: we should do this too at the end of the
2993 * config parsing to free all default values.
2994 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002995 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2996 err_code |= ERR_ABORT;
2997 goto out;
2998 }
2999
Willy Tarreaua534fea2008-08-03 12:19:50 +02003000 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003001 free(defproxy.check_command);
3002 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003003 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003004 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01003005 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003006 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003007 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003008 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003009 free(defproxy.capture_name);
3010 free(defproxy.monitor_uri);
3011 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003012 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003013 free(defproxy.fwdfor_hdr_name);
3014 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003015 free(defproxy.orgto_hdr_name);
3016 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003017 free(defproxy.server_id_hdr_name);
3018 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003019 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003020 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003021 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003022 free(defproxy.expect_regex);
3023 defproxy.expect_regex = NULL;
3024 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003025
Willy Tarreau62a61232013-04-12 18:13:46 +02003026 if (defproxy.conf.logformat_string != default_http_log_format &&
3027 defproxy.conf.logformat_string != default_tcp_log_format &&
3028 defproxy.conf.logformat_string != clf_http_log_format)
3029 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003030
Willy Tarreau62a61232013-04-12 18:13:46 +02003031 free(defproxy.conf.uniqueid_format_string);
3032 free(defproxy.conf.lfs_file);
3033 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003034 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003035 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003036
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003037 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3038 free(defproxy.conf.logformat_sd_string);
3039 free(defproxy.conf.lfsd_file);
3040
Willy Tarreaua534fea2008-08-03 12:19:50 +02003041 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003042 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003043
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 /* we cannot free uri_auth because it might already be used */
3045 init_default_instance();
3046 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003047 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3048 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003049 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
3052 else if (curproxy == NULL) {
3053 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003057
3058 /* update the current file and line being parsed */
3059 curproxy->conf.args.file = curproxy->conf.file;
3060 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003061
3062 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02003063 if (!strcmp(args[0], "server") ||
3064 !strcmp(args[0], "default-server") ||
3065 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02003066 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3067 if (err_code & ERR_FATAL)
3068 goto out;
3069 }
3070 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003071 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003072 int cur_arg;
3073
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 if (curproxy == &defproxy) {
3075 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003079 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081
Willy Tarreau24709282013-03-10 21:32:12 +01003082 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003083 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003088
Willy Tarreaua261e9b2016-12-22 20:44:00 +01003089 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003090
3091 /* use default settings for unix sockets */
3092 bind_conf->ux.uid = global.unix_bind.ux.uid;
3093 bind_conf->ux.gid = global.unix_bind.ux.gid;
3094 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003095
3096 /* NOTE: the following line might create several listeners if there
3097 * are comma-separated IPs or port ranges. So all further processing
3098 * will have to be applied to all listeners created after last_listen.
3099 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003100 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3101 if (errmsg && *errmsg) {
3102 indent_msg(&errmsg, 2);
3103 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003104 }
3105 else
3106 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3107 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003111
Willy Tarreau4348fad2012-09-20 16:48:07 +02003112 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3113 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003114 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003115 }
3116
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003117 cur_arg = 2;
3118 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003119 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003120 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003121 char *err;
3122
Willy Tarreau26982662012-09-12 23:17:10 +02003123 kw = bind_find_kw(args[cur_arg]);
3124 if (kw) {
3125 char *err = NULL;
3126 int code;
3127
3128 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003129 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3130 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003131 cur_arg += 1 + kw->skip ;
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
3134 }
3135
Willy Tarreau4348fad2012-09-20 16:48:07 +02003136 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003137 err_code |= code;
3138
3139 if (code) {
3140 if (err && *err) {
3141 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003142 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003143 }
3144 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003145 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3146 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003147 if (code & ERR_FATAL) {
3148 free(err);
3149 cur_arg += 1 + kw->skip;
3150 goto out;
3151 }
3152 }
3153 free(err);
3154 cur_arg += 1 + kw->skip;
3155 continue;
3156 }
3157
Willy Tarreau8638f482012-09-18 18:01:17 +02003158 err = NULL;
3159 if (!bind_dumped) {
3160 bind_dump_kws(&err);
3161 indent_msg(&err, 4);
3162 bind_dumped = 1;
3163 }
3164
3165 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3166 file, linenum, args[0], args[1], args[cur_arg],
3167 err ? " Registered keywords :" : "", err ? err : "");
3168 free(err);
3169
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003172 }
Willy Tarreau93893792009-07-23 13:19:11 +02003173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 }
3175 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003176 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3178 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003182 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003183 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003184
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 /* flush useless bits */
3186 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003189 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003190 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003192
William Lallemanddf1425a2015-04-28 20:17:49 +02003193 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3194 goto out;
3195
Willy Tarreau1c47f852006-07-09 08:22:27 +02003196 if (!*args[1]) {
3197 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3198 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003201 }
3202
Willy Tarreaua534fea2008-08-03 12:19:50 +02003203 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003204 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003205 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003206 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003207 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3208
Willy Tarreau93893792009-07-23 13:19:11 +02003209 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003212 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3213 goto out;
3214
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3216 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3217 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3218 else {
3219 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 }
3223 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003224 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003225 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003226
3227 if (curproxy == &defproxy) {
3228 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3229 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003232 }
3233
William Lallemanddf1425a2015-04-28 20:17:49 +02003234 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3235 goto out;
3236
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003237 if (!*args[1]) {
3238 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3239 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003242 }
3243
3244 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003245 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003246 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003247
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003248 if (curproxy->uuid <= 0) {
3249 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003250 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003253 }
3254
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003255 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3256 if (node) {
3257 struct proxy *target = container_of(node, struct proxy, conf.id);
3258 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3259 file, linenum, proxy_type_str(curproxy), curproxy->id,
3260 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
3263 }
3264 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003265 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003266 else if (!strcmp(args[0], "description")) {
3267 int i, len=0;
3268 char *d;
3269
Cyril Bonté99ed3272010-01-24 23:29:44 +01003270 if (curproxy == &defproxy) {
3271 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3272 file, linenum, args[0]);
3273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
3275 }
3276
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003277 if (!*args[1]) {
3278 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3279 file, linenum, args[0]);
3280 return -1;
3281 }
3282
Willy Tarreau348acfe2014-04-14 15:00:39 +02003283 for (i = 1; *args[i]; i++)
3284 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003285
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003286 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003287 curproxy->desc = d;
3288
Willy Tarreau348acfe2014-04-14 15:00:39 +02003289 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3290 for (i = 2; *args[i]; i++)
3291 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003292
3293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003295 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 curproxy->state = PR_STSTOPPED;
3298 }
3299 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003300 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 curproxy->state = PR_STNEW;
3303 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003304 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3305 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003306 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003307
3308 while (*args[cur_arg]) {
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003309 if (strcmp(args[cur_arg], "all") == 0) {
3310 set = 0;
3311 break;
3312 }
Christopher Faulet26028f62017-11-22 15:01:51 +01003313 if (parse_process_number(args[cur_arg], &set, NULL, &errmsg)) {
Christopher Fauletf1f0c5f2017-11-22 12:06:43 +01003314 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003317 }
3318 cur_arg++;
3319 }
3320 curproxy->bind_proc = set;
3321 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003322 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003323 if (curproxy == &defproxy) {
3324 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003327 }
3328
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003329 err = invalid_char(args[1]);
3330 if (err) {
3331 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3332 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003334 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003335 }
3336
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003337 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003338 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3339 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003342 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003343 }
3344 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3345
3346 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3347 err_code |= ERR_WARN;
3348
3349 if (*(args[1]) == 0) {
3350 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3351 file, linenum, args[0]);
3352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
3354 }
3355 free(curproxy->dyncookie_key);
3356 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3359 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360
Willy Tarreau977b8e42006-12-29 14:19:17 +01003361 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003363
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 if (*(args[1]) == 0) {
3365 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3366 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003370
Willy Tarreau67402132012-05-31 20:40:20 +02003371 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003372 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003373 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003374 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 curproxy->cookie_name = strdup(args[1]);
3376 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003377
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 cur_arg = 2;
3379 while (*(args[cur_arg])) {
3380 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003381 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }
3383 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003384 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
3386 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003387 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 }
3389 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003390 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 }
3392 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003393 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003395 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003396 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003397 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003399 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003401 else if (!strcmp(args[cur_arg], "httponly")) {
3402 curproxy->ck_opts |= PR_CK_HTTPONLY;
3403 }
3404 else if (!strcmp(args[cur_arg], "secure")) {
3405 curproxy->ck_opts |= PR_CK_SECURE;
3406 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003407 else if (!strcmp(args[cur_arg], "domain")) {
3408 if (!*args[cur_arg + 1]) {
3409 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3410 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003413 }
3414
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003415 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003416 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003417 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3418 " dots nor does not start with a dot."
3419 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003420 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003421 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003422 }
3423
3424 err = invalid_domainchar(args[cur_arg + 1]);
3425 if (err) {
3426 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3427 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003430 }
3431
Willy Tarreau68a897b2009-12-03 23:28:34 +01003432 if (!curproxy->cookie_domain) {
3433 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3434 } else {
3435 /* one domain was already specified, add another one by
3436 * building the string which will be returned along with
3437 * the cookie.
3438 */
3439 char *new_ptr;
3440 int new_len = strlen(curproxy->cookie_domain) +
3441 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3442 new_ptr = malloc(new_len);
3443 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3444 free(curproxy->cookie_domain);
3445 curproxy->cookie_domain = new_ptr;
3446 }
Willy Tarreau31936852010-10-06 16:59:56 +02003447 cur_arg++;
3448 }
3449 else if (!strcmp(args[cur_arg], "maxidle")) {
3450 unsigned int maxidle;
3451 const char *res;
3452
3453 if (!*args[cur_arg + 1]) {
3454 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3455 file, linenum, args[cur_arg]);
3456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
3458 }
3459
3460 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3461 if (res) {
3462 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3463 file, linenum, *res, args[cur_arg]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467 curproxy->cookie_maxidle = maxidle;
3468 cur_arg++;
3469 }
3470 else if (!strcmp(args[cur_arg], "maxlife")) {
3471 unsigned int maxlife;
3472 const char *res;
3473
3474 if (!*args[cur_arg + 1]) {
3475 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3476 file, linenum, args[cur_arg]);
3477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480
3481 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3482 if (res) {
3483 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3484 file, linenum, *res, args[cur_arg]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003489 cur_arg++;
3490 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003491 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003492
3493 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3494 err_code |= ERR_WARN;
3495 curproxy->ck_opts |= PR_CK_DYNAMIC;
3496 }
3497
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003499 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 +02003500 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
3504 cur_arg++;
3505 }
Willy Tarreau67402132012-05-31 20:40:20 +02003506 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3508 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
3511
Willy Tarreau67402132012-05-31 20:40:20 +02003512 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3514 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003517
Willy Tarreau67402132012-05-31 20:40:20 +02003518 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003519 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3520 file, linenum);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003524 else if (!strcmp(args[0], "email-alert")) {
3525 if (*(args[1]) == 0) {
3526 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3527 file, linenum, args[0]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531
3532 if (!strcmp(args[1], "from")) {
3533 if (*(args[1]) == 0) {
3534 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3535 file, linenum, args[1]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 free(curproxy->email_alert.from);
3540 curproxy->email_alert.from = strdup(args[2]);
3541 }
3542 else if (!strcmp(args[1], "mailers")) {
3543 if (*(args[1]) == 0) {
3544 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3545 file, linenum, args[1]);
3546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
3548 }
3549 free(curproxy->email_alert.mailers.name);
3550 curproxy->email_alert.mailers.name = strdup(args[2]);
3551 }
3552 else if (!strcmp(args[1], "myhostname")) {
3553 if (*(args[1]) == 0) {
3554 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3555 file, linenum, args[1]);
3556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
3558 }
3559 free(curproxy->email_alert.myhostname);
3560 curproxy->email_alert.myhostname = strdup(args[2]);
3561 }
Simon Horman64e34162015-02-06 11:11:57 +09003562 else if (!strcmp(args[1], "level")) {
3563 curproxy->email_alert.level = get_log_level(args[2]);
3564 if (curproxy->email_alert.level < 0) {
3565 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3566 file, linenum, args[1], args[2]);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
3570 }
Simon Horman9dc49962015-01-30 11:22:59 +09003571 else if (!strcmp(args[1], "to")) {
3572 if (*(args[1]) == 0) {
3573 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3574 file, linenum, args[1]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578 free(curproxy->email_alert.to);
3579 curproxy->email_alert.to = strdup(args[2]);
3580 }
3581 else {
3582 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3583 file, linenum, args[1]);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586 }
Simon Horman64e34162015-02-06 11:11:57 +09003587 /* Indicate that the email_alert is at least partially configured */
3588 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003589 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003590 else if (!strcmp(args[0], "external-check")) {
3591 if (*(args[1]) == 0) {
3592 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3593 file, linenum, args[0]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597
3598 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003599 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003600 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003601 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003602 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3603 file, linenum, args[1]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607 free(curproxy->check_command);
3608 curproxy->check_command = strdup(args[2]);
3609 }
3610 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003611 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003612 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003613 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003614 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3615 file, linenum, args[1]);
3616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
3618 }
3619 free(curproxy->check_path);
3620 curproxy->check_path = strdup(args[2]);
3621 }
3622 else {
3623 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3624 file, linenum, args[1]);
3625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
3627 }
3628 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003629 else if (!strcmp(args[0], "persist")) { /* persist */
3630 if (*(args[1]) == 0) {
3631 Alert("parsing [%s:%d] : missing persist method.\n",
3632 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003635 }
3636
3637 if (!strncmp(args[1], "rdp-cookie", 10)) {
3638 curproxy->options2 |= PR_O2_RDPC_PRST;
3639
Emeric Brunb982a3d2010-01-04 15:45:53 +01003640 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003641 const char *beg, *end;
3642
3643 beg = args[1] + 11;
3644 end = strchr(beg, ')');
3645
William Lallemanddf1425a2015-04-28 20:17:49 +02003646 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3647 goto out;
3648
Emeric Brun647caf12009-06-30 17:57:00 +02003649 if (!end || end == beg) {
3650 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3651 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003654 }
3655
3656 free(curproxy->rdp_cookie_name);
3657 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3658 curproxy->rdp_cookie_len = end-beg;
3659 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003660 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003661 free(curproxy->rdp_cookie_name);
3662 curproxy->rdp_cookie_name = strdup("msts");
3663 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3664 }
3665 else { /* syntax */
3666 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3667 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003670 }
3671 }
3672 else {
3673 Alert("parsing [%s:%d] : unknown persist method.\n",
3674 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003677 }
3678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003680 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003684 else if (!strcmp(args[0], "load-server-state-from-file")) {
3685 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3686 err_code |= ERR_WARN;
3687 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3688 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3689 }
3690 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3691 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3692 }
3693 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3694 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3695 }
3696 else {
3697 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3698 file, linenum, args[0], args[1]);
3699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
3701 }
3702 }
3703 else if (!strcmp(args[0], "server-state-file-name")) {
3704 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3705 err_code |= ERR_WARN;
3706 if (*(args[1]) == 0) {
3707 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3708 file, linenum, args[0]);
3709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
3711 }
3712 else if (!strcmp(args[1], "use-backend-name"))
3713 curproxy->server_state_file_name = strdup(curproxy->id);
3714 else
3715 curproxy->server_state_file_name = strdup(args[1]);
3716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003718 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003720
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003722 if (curproxy == &defproxy) {
3723 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727
William Lallemand1a748ae2015-05-19 16:37:23 +02003728 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3729 goto out;
3730
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 if (*(args[4]) == 0) {
3732 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3733 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003737 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 curproxy->capture_name = strdup(args[2]);
3739 curproxy->capture_namelen = strlen(curproxy->capture_name);
3740 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 curproxy->to_log |= LW_COOKIE;
3742 }
3743 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3744 struct cap_hdr *hdr;
3745
3746 if (curproxy == &defproxy) {
3747 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 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 }
3751
William Lallemand1a748ae2015-05-19 16:37:23 +02003752 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3753 goto out;
3754
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3756 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3757 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 }
3761
Vincent Bernat02779b62016-04-03 13:48:43 +02003762 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763 hdr->next = curproxy->req_cap;
3764 hdr->name = strdup(args[3]);
3765 hdr->namelen = strlen(args[3]);
3766 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003767 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 hdr->index = curproxy->nb_req_cap++;
3769 curproxy->req_cap = hdr;
3770 curproxy->to_log |= LW_REQHDR;
3771 }
3772 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3773 struct cap_hdr *hdr;
3774
3775 if (curproxy == &defproxy) {
3776 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 +02003777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 }
3780
William Lallemand1a748ae2015-05-19 16:37:23 +02003781 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3782 goto out;
3783
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3785 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3786 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003790 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 hdr->next = curproxy->rsp_cap;
3792 hdr->name = strdup(args[3]);
3793 hdr->namelen = strlen(args[3]);
3794 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003795 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 hdr->index = curproxy->nb_rsp_cap++;
3797 curproxy->rsp_cap = hdr;
3798 curproxy->to_log |= LW_RSPHDR;
3799 }
3800 else {
3801 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3802 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
3806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003810
William Lallemanddf1425a2015-04-28 20:17:49 +02003811 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3812 goto out;
3813
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 if (*(args[1]) == 0) {
3815 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3816 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 }
3820 curproxy->conn_retries = atol(args[1]);
3821 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003822 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003823 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003824
3825 if (curproxy == &defproxy) {
3826 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830
Willy Tarreau20b0de52012-12-24 15:45:22 +01003831 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003832 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003833 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3834 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3835 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3836 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003837 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 +01003838 file, linenum, args[0]);
3839 err_code |= ERR_WARN;
3840 }
3841
Willy Tarreauff011f22011-01-06 17:51:27 +01003842 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003843
Willy Tarreauff011f22011-01-06 17:51:27 +01003844 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003845 err_code |= ERR_ALERT | ERR_ABORT;
3846 goto out;
3847 }
3848
Willy Tarreau5002f572014-04-23 01:32:02 +02003849 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003850 err_code |= warnif_cond_conflicts(rule->cond,
3851 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3852 file, linenum);
3853
Willy Tarreauff011f22011-01-06 17:51:27 +01003854 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003855 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003856 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003857 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003858
3859 if (curproxy == &defproxy) {
3860 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
3863 }
3864
3865 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003866 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003867 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3868 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003869 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3870 file, linenum, args[0]);
3871 err_code |= ERR_WARN;
3872 }
3873
3874 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3875
3876 if (!rule) {
3877 err_code |= ERR_ALERT | ERR_ABORT;
3878 goto out;
3879 }
3880
3881 err_code |= warnif_cond_conflicts(rule->cond,
3882 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3883 file, linenum);
3884
3885 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3886 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003887 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3888 /* set the header name and length into the proxy structure */
3889 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3890 err_code |= ERR_WARN;
3891
3892 if (!*args[1]) {
3893 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3894 file, linenum, args[0]);
3895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
3897 }
3898
3899 /* set the desired header name */
3900 free(curproxy->server_id_hdr_name);
3901 curproxy->server_id_hdr_name = strdup(args[1]);
3902 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3903 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003904 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003905 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003906
Willy Tarreaub099aca2008-10-12 17:26:37 +02003907 if (curproxy == &defproxy) {
3908 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003911 }
3912
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003913 /* emulate "block" using "http-request block". Since these rules are supposed to
3914 * be processed before all http-request rules, we put them into their own list
3915 * and will insert them at the end.
3916 */
3917 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3918 if (!rule) {
3919 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003920 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003921 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003922 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3923 err_code |= warnif_cond_conflicts(rule->cond,
3924 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3925 file, linenum);
3926 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003927
3928 if (!already_warned(WARN_BLOCK_DEPRECATED))
3929 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]);
3930
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003931 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003932 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003933 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003934
Cyril Bonté99ed3272010-01-24 23:29:44 +01003935 if (curproxy == &defproxy) {
3936 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
3939 }
3940
Willy Tarreaube4653b2015-05-28 15:26:58 +02003941 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003942 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3943 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003946 }
3947
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003948 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003949 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003950 err_code |= warnif_cond_conflicts(rule->cond,
3951 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3952 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003953 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003954 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003955 struct switching_rule *rule;
3956
Willy Tarreaub099aca2008-10-12 17:26:37 +02003957 if (curproxy == &defproxy) {
3958 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003961 }
3962
Willy Tarreau55ea7572007-06-17 19:56:27 +02003963 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003965
3966 if (*(args[1]) == 0) {
3967 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003970 }
3971
Willy Tarreauf51658d2014-04-23 01:21:56 +02003972 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003973 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003974 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3975 file, linenum, errmsg);
3976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
3978 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003979
Willy Tarreauf51658d2014-04-23 01:21:56 +02003980 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003981 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003982 else if (*args[2]) {
3983 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3984 file, linenum, args[2]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003988
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003989 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003990 if (!rule) {
3991 Alert("Out of memory error.\n");
3992 goto out;
3993 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003994 rule->cond = cond;
3995 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003996 rule->line = linenum;
3997 rule->file = strdup(file);
3998 if (!rule->file) {
3999 Alert("Out of memory error.\n");
4000 goto out;
4001 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004002 LIST_INIT(&rule->list);
4003 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4004 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004005 else if (strcmp(args[0], "use-server") == 0) {
4006 struct server_rule *rule;
4007
4008 if (curproxy == &defproxy) {
4009 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
4012 }
4013
4014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4015 err_code |= ERR_WARN;
4016
4017 if (*(args[1]) == 0) {
4018 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022
4023 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4024 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4025 file, linenum, args[0]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
4029
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004030 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004031 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4032 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004037 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004038
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004039 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004040 rule->cond = cond;
4041 rule->srv.name = strdup(args[1]);
4042 LIST_INIT(&rule->list);
4043 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4044 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4045 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004046 else if ((!strcmp(args[0], "force-persist")) ||
4047 (!strcmp(args[0], "ignore-persist"))) {
4048 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004049
4050 if (curproxy == &defproxy) {
4051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055
4056 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4057 err_code |= ERR_WARN;
4058
Willy Tarreauef6494c2010-01-28 17:12:36 +01004059 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004060 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4061 file, linenum, args[0]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004066 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004067 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4068 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004073 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4074 * where force-persist is applied.
4075 */
4076 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004077
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004078 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004079 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004080 if (!strcmp(args[0], "force-persist")) {
4081 rule->type = PERSIST_TYPE_FORCE;
4082 } else {
4083 rule->type = PERSIST_TYPE_IGNORE;
4084 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004085 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004086 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004087 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004088 else if (!strcmp(args[0], "stick-table")) {
4089 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004090 struct proxy *other;
4091
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004092 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004093 if (other) {
4094 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4095 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099
Emeric Brun32da3c42010-09-23 18:39:19 +02004100 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004101 curproxy->table.type = (unsigned int)-1;
4102 while (*args[myidx]) {
4103 const char *err;
4104
4105 if (strcmp(args[myidx], "size") == 0) {
4106 myidx++;
4107 if (!*(args[myidx])) {
4108 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4109 file, linenum, args[myidx-1]);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
4113 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4114 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4115 file, linenum, *err, args[myidx-1]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004119 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004120 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004121 else if (strcmp(args[myidx], "peers") == 0) {
4122 myidx++;
Godbach50523162013-12-11 19:48:57 +08004123 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004124 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4125 file, linenum, args[myidx-1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
Godbach50523162013-12-11 19:48:57 +08004128 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004129 curproxy->table.peers.name = strdup(args[myidx++]);
4130 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 else if (strcmp(args[myidx], "expire") == 0) {
4132 myidx++;
4133 if (!*(args[myidx])) {
4134 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4135 file, linenum, args[myidx-1]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
4139 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4140 if (err) {
4141 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4142 file, linenum, *err, args[myidx-1]);
4143 err_code |= ERR_ALERT | ERR_FATAL;
4144 goto out;
4145 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004146 if (val > INT_MAX) {
4147 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4148 file, linenum, val);
4149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
4151 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004153 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004154 }
4155 else if (strcmp(args[myidx], "nopurge") == 0) {
4156 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004157 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 }
4159 else if (strcmp(args[myidx], "type") == 0) {
4160 myidx++;
4161 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4162 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4163 file, linenum, args[myidx]);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004167 /* myidx already points to next arg */
4168 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004169 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004170 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004171 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004172
4173 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004174 nw = args[myidx];
4175 while (*nw) {
4176 /* the "store" keyword supports a comma-separated list */
4177 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004178 sa = NULL; /* store arg */
4179 while (*nw && *nw != ',') {
4180 if (*nw == '(') {
4181 *nw = 0;
4182 sa = ++nw;
4183 while (*nw != ')') {
4184 if (!*nw) {
4185 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4186 file, linenum, args[0], cw);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190 nw++;
4191 }
4192 *nw = '\0';
4193 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004194 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004195 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004196 if (*nw)
4197 *nw++ = '\0';
4198 type = stktable_get_data_type(cw);
4199 if (type < 0) {
4200 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4201 file, linenum, args[0], cw);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
Willy Tarreauac782882010-06-20 10:41:54 +02004205
4206 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4207 switch (err) {
4208 case PE_NONE: break;
4209 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004210 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4211 file, linenum, args[0], cw);
4212 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004213 break;
4214
4215 case PE_ARG_MISSING:
4216 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4217 file, linenum, args[0], cw);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220
4221 case PE_ARG_NOT_USED:
4222 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4223 file, linenum, args[0], cw);
4224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
4226
4227 default:
4228 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4229 file, linenum, args[0], cw);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004232 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004233 }
4234 myidx++;
4235 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004236 else {
4237 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4238 file, linenum, args[myidx]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004241 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004242 }
4243
4244 if (!curproxy->table.size) {
4245 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4246 file, linenum);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250
4251 if (curproxy->table.type == (unsigned int)-1) {
4252 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4253 file, linenum);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257 }
4258 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004259 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004260 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004261 int myidx = 0;
4262 const char *name = NULL;
4263 int flags;
4264
4265 if (curproxy == &defproxy) {
4266 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270
4271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4272 err_code |= ERR_WARN;
4273 goto out;
4274 }
4275
4276 myidx++;
4277 if ((strcmp(args[myidx], "store") == 0) ||
4278 (strcmp(args[myidx], "store-request") == 0)) {
4279 myidx++;
4280 flags = STK_IS_STORE;
4281 }
4282 else if (strcmp(args[myidx], "store-response") == 0) {
4283 myidx++;
4284 flags = STK_IS_STORE | STK_ON_RSP;
4285 }
4286 else if (strcmp(args[myidx], "match") == 0) {
4287 myidx++;
4288 flags = STK_IS_MATCH;
4289 }
4290 else if (strcmp(args[myidx], "on") == 0) {
4291 myidx++;
4292 flags = STK_IS_MATCH | STK_IS_STORE;
4293 }
4294 else {
4295 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299
4300 if (*(args[myidx]) == 0) {
4301 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
4304 }
4305
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004306 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004307 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004308 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004309 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313
4314 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004315 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4316 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4317 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004318 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004319 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004320 goto out;
4321 }
4322 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004323 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4324 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\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 }
4331
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004332 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004333 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004334
Emeric Brunb982a3d2010-01-04 15:45:53 +01004335 if (strcmp(args[myidx], "table") == 0) {
4336 myidx++;
4337 name = args[myidx++];
4338 }
4339
Willy Tarreauef6494c2010-01-28 17:12:36 +01004340 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004341 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004342 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4343 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004344 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004345 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004346 goto out;
4347 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004348 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004349 else if (*(args[myidx])) {
4350 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4351 file, linenum, args[0], args[myidx]);
4352 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004353 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004354 goto out;
4355 }
Emeric Brun97679e72010-09-23 17:56:44 +02004356 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004357 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004358 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004359 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004360
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004361 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004362 rule->cond = cond;
4363 rule->expr = expr;
4364 rule->flags = flags;
4365 rule->table.name = name ? strdup(name) : NULL;
4366 LIST_INIT(&rule->list);
4367 if (flags & STK_ON_RSP)
4368 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4369 else
4370 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 else if (!strcmp(args[0], "stats")) {
4373 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4374 curproxy->uri_auth = NULL; /* we must detach from the default config */
4375
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004376 if (!*args[1]) {
4377 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004378 } else if (!strcmp(args[1], "admin")) {
4379 struct stats_admin_rule *rule;
4380
4381 if (curproxy == &defproxy) {
4382 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 }
4386
4387 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4388 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4389 err_code |= ERR_ALERT | ERR_ABORT;
4390 goto out;
4391 }
4392
4393 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4394 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4395 file, linenum, args[0], args[1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004399 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004400 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4401 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
4404 }
4405
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004406 err_code |= warnif_cond_conflicts(cond,
4407 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4408 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004409
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004410 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004411 rule->cond = cond;
4412 LIST_INIT(&rule->list);
4413 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 } else if (!strcmp(args[1], "uri")) {
4415 if (*(args[2]) == 0) {
4416 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4420 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_ALERT | ERR_ABORT;
4422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 }
4424 } else if (!strcmp(args[1], "realm")) {
4425 if (*(args[2]) == 0) {
4426 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004429 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4430 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_ALERT | ERR_ABORT;
4432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004434 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004435 unsigned interval;
4436
4437 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4438 if (err) {
4439 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4440 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004441 err_code |= ERR_ALERT | ERR_FATAL;
4442 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004443 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4444 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_ABORT;
4446 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004447 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004448 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004449 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004450
4451 if (curproxy == &defproxy) {
4452 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456
4457 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4458 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4459 err_code |= ERR_ALERT | ERR_ABORT;
4460 goto out;
4461 }
4462
Willy Tarreauff011f22011-01-06 17:51:27 +01004463 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004464 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004465 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4466 file, linenum, args[0]);
4467 err_code |= ERR_WARN;
4468 }
4469
Willy Tarreauff011f22011-01-06 17:51:27 +01004470 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004471
Willy Tarreauff011f22011-01-06 17:51:27 +01004472 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004473 err_code |= ERR_ALERT | ERR_ABORT;
4474 goto out;
4475 }
4476
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004477 err_code |= warnif_cond_conflicts(rule->cond,
4478 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4479 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004480 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004481
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 } else if (!strcmp(args[1], "auth")) {
4483 if (*(args[2]) == 0) {
4484 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004487 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4488 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= ERR_ALERT | ERR_ABORT;
4490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 }
4492 } else if (!strcmp(args[1], "scope")) {
4493 if (*(args[2]) == 0) {
4494 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4498 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_ABORT;
4500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 }
4502 } else if (!strcmp(args[1], "enable")) {
4503 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4504 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_ALERT | ERR_ABORT;
4506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004508 } else if (!strcmp(args[1], "hide-version")) {
4509 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4510 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004511 err_code |= ERR_ALERT | ERR_ABORT;
4512 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004513 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004514 } else if (!strcmp(args[1], "show-legends")) {
4515 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4516 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4517 err_code |= ERR_ALERT | ERR_ABORT;
4518 goto out;
4519 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004520 } else if (!strcmp(args[1], "show-node")) {
4521
4522 if (*args[2]) {
4523 int i;
4524 char c;
4525
4526 for (i=0; args[2][i]; i++) {
4527 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004528 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4529 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004530 break;
4531 }
4532
4533 if (!i || args[2][i]) {
4534 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4535 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4536 file, linenum, args[0], args[1]);
4537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
4540 }
4541
4542 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4543 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4544 err_code |= ERR_ALERT | ERR_ABORT;
4545 goto out;
4546 }
4547 } else if (!strcmp(args[1], "show-desc")) {
4548 char *desc = NULL;
4549
4550 if (*args[2]) {
4551 int i, len=0;
4552 char *d;
4553
Willy Tarreau348acfe2014-04-14 15:00:39 +02004554 for (i = 2; *args[i]; i++)
4555 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004556
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004557 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004558
Willy Tarreau348acfe2014-04-14 15:00:39 +02004559 d += snprintf(d, desc + len - d, "%s", args[2]);
4560 for (i = 3; *args[i]; i++)
4561 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004562 }
4563
4564 if (!*args[2] && !global.desc)
4565 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4566 file, linenum, args[1]);
4567 else {
4568 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4569 free(desc);
4570 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4571 err_code |= ERR_ALERT | ERR_ABORT;
4572 goto out;
4573 }
4574 free(desc);
4575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004577stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004578 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 +01004579 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583 }
4584 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004585 int optnum;
4586
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004587 if (*(args[1]) == '\0') {
4588 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4589 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004593
4594 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4595 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004596 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4597 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4598 file, linenum, cfg_opts[optnum].name);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004602 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4603 goto out;
4604
Willy Tarreau93893792009-07-23 13:19:11 +02004605 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4606 err_code |= ERR_WARN;
4607 goto out;
4608 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004609
Willy Tarreau3842f002009-06-14 11:39:52 +02004610 curproxy->no_options &= ~cfg_opts[optnum].val;
4611 curproxy->options &= ~cfg_opts[optnum].val;
4612
4613 switch (kwm) {
4614 case KWM_STD:
4615 curproxy->options |= cfg_opts[optnum].val;
4616 break;
4617 case KWM_NO:
4618 curproxy->no_options |= cfg_opts[optnum].val;
4619 break;
4620 case KWM_DEF: /* already cleared */
4621 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004622 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004623
Willy Tarreau93893792009-07-23 13:19:11 +02004624 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004625 }
4626 }
4627
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004628 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4629 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004630 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4631 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4632 file, linenum, cfg_opts2[optnum].name);
4633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004636 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4637 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004638 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4639 err_code |= ERR_WARN;
4640 goto out;
4641 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004642
Willy Tarreau3842f002009-06-14 11:39:52 +02004643 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4644 curproxy->options2 &= ~cfg_opts2[optnum].val;
4645
4646 switch (kwm) {
4647 case KWM_STD:
4648 curproxy->options2 |= cfg_opts2[optnum].val;
4649 break;
4650 case KWM_NO:
4651 curproxy->no_options2 |= cfg_opts2[optnum].val;
4652 break;
4653 case KWM_DEF: /* already cleared */
4654 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004655 }
Willy Tarreau93893792009-07-23 13:19:11 +02004656 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004657 }
4658 }
4659
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004660 /* HTTP options override each other. They can be cancelled using
4661 * "no option xxx" which only switches to default mode if the mode
4662 * was this one (useful for cancelling options set in defaults
4663 * sections).
4664 */
4665 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004666 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4667 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004668 if (kwm == KWM_STD) {
4669 curproxy->options &= ~PR_O_HTTP_MODE;
4670 curproxy->options |= PR_O_HTTP_PCL;
4671 goto out;
4672 }
4673 else if (kwm == KWM_NO) {
4674 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4675 curproxy->options &= ~PR_O_HTTP_MODE;
4676 goto out;
4677 }
4678 }
4679 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004680 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4681 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004682 if (kwm == KWM_STD) {
4683 curproxy->options &= ~PR_O_HTTP_MODE;
4684 curproxy->options |= PR_O_HTTP_FCL;
4685 goto out;
4686 }
4687 else if (kwm == KWM_NO) {
4688 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4689 curproxy->options &= ~PR_O_HTTP_MODE;
4690 goto out;
4691 }
4692 }
4693 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004694 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4695 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004696 if (kwm == KWM_STD) {
4697 curproxy->options &= ~PR_O_HTTP_MODE;
4698 curproxy->options |= PR_O_HTTP_SCL;
4699 goto out;
4700 }
4701 else if (kwm == KWM_NO) {
4702 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4703 curproxy->options &= ~PR_O_HTTP_MODE;
4704 goto out;
4705 }
4706 }
4707 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004708 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4709 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004710 if (kwm == KWM_STD) {
4711 curproxy->options &= ~PR_O_HTTP_MODE;
4712 curproxy->options |= PR_O_HTTP_KAL;
4713 goto out;
4714 }
4715 else if (kwm == KWM_NO) {
4716 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4717 curproxy->options &= ~PR_O_HTTP_MODE;
4718 goto out;
4719 }
4720 }
4721 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004722 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4723 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004724 if (kwm == KWM_STD) {
4725 curproxy->options &= ~PR_O_HTTP_MODE;
4726 curproxy->options |= PR_O_HTTP_TUN;
4727 goto out;
4728 }
4729 else if (kwm == KWM_NO) {
4730 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4731 curproxy->options &= ~PR_O_HTTP_MODE;
4732 goto out;
4733 }
4734 }
4735
Joseph Lynch726ab712015-05-11 23:25:34 -07004736 /* Redispatch can take an integer argument that control when the
4737 * resispatch occurs. All values are relative to the retries option.
4738 * This can be cancelled using "no option xxx".
4739 */
4740 if (strcmp(args[1], "redispatch") == 0) {
4741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4742 err_code |= ERR_WARN;
4743 goto out;
4744 }
4745
4746 curproxy->no_options &= ~PR_O_REDISP;
4747 curproxy->options &= ~PR_O_REDISP;
4748
4749 switch (kwm) {
4750 case KWM_STD:
4751 curproxy->options |= PR_O_REDISP;
4752 curproxy->redispatch_after = -1;
4753 if(*args[2]) {
4754 curproxy->redispatch_after = atol(args[2]);
4755 }
4756 break;
4757 case KWM_NO:
4758 curproxy->no_options |= PR_O_REDISP;
4759 curproxy->redispatch_after = 0;
4760 break;
4761 case KWM_DEF: /* already cleared */
4762 break;
4763 }
4764 goto out;
4765 }
4766
Willy Tarreau3842f002009-06-14 11:39:52 +02004767 if (kwm != KWM_STD) {
4768 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004769 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004772 }
4773
Emeric Brun3a058f32009-06-30 18:26:00 +02004774 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004775 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004777 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004778 if (*(args[2]) != '\0') {
4779 if (!strcmp(args[2], "clf")) {
4780 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004781 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004782 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004783 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004786 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004787 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4788 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004789 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004790 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4791 char *oldlogformat = "log-format";
4792 char *clflogformat = "";
4793
4794 if (curproxy->conf.logformat_string == default_http_log_format)
4795 oldlogformat = "option httplog";
4796 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4797 oldlogformat = "option tcplog";
4798 else if (curproxy->conf.logformat_string == clf_http_log_format)
4799 oldlogformat = "option httplog clf";
4800 if (logformat == clf_http_log_format)
4801 clflogformat = " clf";
4802 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4803 file, linenum, clflogformat, oldlogformat);
4804 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004805 if (curproxy->conf.logformat_string != default_http_log_format &&
4806 curproxy->conf.logformat_string != default_tcp_log_format &&
4807 curproxy->conf.logformat_string != clf_http_log_format)
4808 free(curproxy->conf.logformat_string);
4809 curproxy->conf.logformat_string = logformat;
4810
4811 free(curproxy->conf.lfs_file);
4812 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4813 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004814 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004815 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004816 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4817 char *oldlogformat = "log-format";
4818
4819 if (curproxy->conf.logformat_string == default_http_log_format)
4820 oldlogformat = "option httplog";
4821 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4822 oldlogformat = "option tcplog";
4823 else if (curproxy->conf.logformat_string == clf_http_log_format)
4824 oldlogformat = "option httplog clf";
4825 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4826 file, linenum, oldlogformat);
4827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004829 if (curproxy->conf.logformat_string != default_http_log_format &&
4830 curproxy->conf.logformat_string != default_tcp_log_format &&
4831 curproxy->conf.logformat_string != clf_http_log_format)
4832 free(curproxy->conf.logformat_string);
4833 curproxy->conf.logformat_string = default_tcp_log_format;
4834
4835 free(curproxy->conf.lfs_file);
4836 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4837 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004838
4839 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4840 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004843 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004844 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004845 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004846
William Lallemanddf1425a2015-04-28 20:17:49 +02004847 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4848 goto out;
4849
Willy Tarreau13943ab2006-12-31 00:24:10 +01004850 if (curproxy->cap & PR_CAP_FE)
4851 curproxy->options |= PR_O_TCP_CLI_KA;
4852 if (curproxy->cap & PR_CAP_BE)
4853 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 }
4855 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004856 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004857 err_code |= ERR_WARN;
4858
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004860 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004861 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004862 curproxy->options2 &= ~PR_O2_CHK_ANY;
4863 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 if (!*args[2]) { /* no argument */
4865 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4866 curproxy->check_len = strlen(DEF_CHECK_REQ);
4867 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004868 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004869 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004871 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004873 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 if (*args[4])
4875 reqlen += strlen(args[4]);
4876 else
4877 reqlen += strlen("HTTP/1.0");
4878
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004879 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004881 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004883 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4884 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004885 }
4886 else if (!strcmp(args[1], "ssl-hello-chk")) {
4887 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004888 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004889 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004890
Willy Tarreaua534fea2008-08-03 12:19:50 +02004891 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004892 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004893 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004894 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004895
4896 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
Willy Tarreau23677902007-05-08 23:50:35 +02004899 else if (!strcmp(args[1], "smtpchk")) {
4900 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004901 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004902 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004903 curproxy->options2 &= ~PR_O2_CHK_ANY;
4904 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004905
4906 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4907 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4908 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4909 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4910 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4911 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004912 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004913 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4914 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4915 } else {
4916 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4917 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4918 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4919 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4920 }
4921 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004922 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4923 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004924 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004925 else if (!strcmp(args[1], "pgsql-check")) {
4926 /* use PostgreSQL request to check servers' health */
4927 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4928 err_code |= ERR_WARN;
4929
4930 free(curproxy->check_req);
4931 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004932 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004933 curproxy->options2 |= PR_O2_PGSQL_CHK;
4934
4935 if (*(args[2])) {
4936 int cur_arg = 2;
4937
4938 while (*(args[cur_arg])) {
4939 if (strcmp(args[cur_arg], "user") == 0) {
4940 char * packet;
4941 uint32_t packet_len;
4942 uint32_t pv;
4943
4944 /* suboption header - needs additional argument for it */
4945 if (*(args[cur_arg+1]) == 0) {
4946 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4947 file, linenum, args[0], args[1], args[cur_arg]);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
4951
4952 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4953 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4954 pv = htonl(0x30000); /* protocol version 3.0 */
4955
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004956 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004957
4958 memcpy(packet + 4, &pv, 4);
4959
4960 /* copy "user" */
4961 memcpy(packet + 8, "user", 4);
4962
4963 /* copy username */
4964 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4965
4966 free(curproxy->check_req);
4967 curproxy->check_req = packet;
4968 curproxy->check_len = packet_len;
4969
4970 packet_len = htonl(packet_len);
4971 memcpy(packet, &packet_len, 4);
4972 cur_arg += 2;
4973 } else {
4974 /* unknown suboption - catchall */
4975 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4976 file, linenum, args[0], args[1]);
4977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
4979 }
4980 } /* end while loop */
4981 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004982 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4983 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004984 }
4985
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004986 else if (!strcmp(args[1], "redis-check")) {
4987 /* use REDIS PING request to check servers' health */
4988 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4989 err_code |= ERR_WARN;
4990
4991 free(curproxy->check_req);
4992 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004993 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004994 curproxy->options2 |= PR_O2_REDIS_CHK;
4995
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004996 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004997 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4998 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004999
5000 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5001 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02005002 }
5003
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005004 else if (!strcmp(args[1], "mysql-check")) {
5005 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005006 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5007 err_code |= ERR_WARN;
5008
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005009 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01005010 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005011 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005012 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005013
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005014 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005015 * const char mysql40_client_auth_pkt[] = {
5016 * "\x0e\x00\x00" // packet length
5017 * "\x01" // packet number
5018 * "\x00\x00" // client capabilities
5019 * "\x00\x00\x01" // max packet
5020 * "haproxy\x00" // username (null terminated string)
5021 * "\x00" // filler (always 0x00)
5022 * "\x01\x00\x00" // packet length
5023 * "\x00" // packet number
5024 * "\x01" // COM_QUIT command
5025 * };
5026 */
5027
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005028 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5029 * const char mysql41_client_auth_pkt[] = {
5030 * "\x0e\x00\x00\" // packet length
5031 * "\x01" // packet number
5032 * "\x00\x00\x00\x00" // client capabilities
5033 * "\x00\x00\x00\x01" // max packet
5034 * "\x21" // character set (UTF-8)
5035 * char[23] // All zeroes
5036 * "haproxy\x00" // username (null terminated string)
5037 * "\x00" // filler (always 0x00)
5038 * "\x01\x00\x00" // packet length
5039 * "\x00" // packet number
5040 * "\x01" // COM_QUIT command
5041 * };
5042 */
5043
5044
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005045 if (*(args[2])) {
5046 int cur_arg = 2;
5047
5048 while (*(args[cur_arg])) {
5049 if (strcmp(args[cur_arg], "user") == 0) {
5050 char *mysqluser;
5051 int packetlen, reqlen, userlen;
5052
5053 /* suboption header - needs additional argument for it */
5054 if (*(args[cur_arg+1]) == 0) {
5055 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5056 file, linenum, args[0], args[1], args[cur_arg]);
5057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
5059 }
5060 mysqluser = args[cur_arg + 1];
5061 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005062
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005063 if (*(args[cur_arg+2])) {
5064 if (!strcmp(args[cur_arg+2], "post-41")) {
5065 packetlen = userlen + 7 + 27;
5066 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005067
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005068 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005069 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005070 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005071
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005072 snprintf(curproxy->check_req, 4, "%c%c%c",
5073 ((unsigned char) packetlen & 0xff),
5074 ((unsigned char) (packetlen >> 8) & 0xff),
5075 ((unsigned char) (packetlen >> 16) & 0xff));
5076
5077 curproxy->check_req[3] = 1;
5078 curproxy->check_req[5] = 130;
5079 curproxy->check_req[11] = 1;
5080 curproxy->check_req[12] = 33;
5081 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5082 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5083 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5084 cur_arg += 3;
5085 } else {
5086 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
5089 }
5090 } else {
5091 packetlen = userlen + 7;
5092 reqlen = packetlen + 9;
5093
5094 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005095 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005096 curproxy->check_len = reqlen;
5097
5098 snprintf(curproxy->check_req, 4, "%c%c%c",
5099 ((unsigned char) packetlen & 0xff),
5100 ((unsigned char) (packetlen >> 8) & 0xff),
5101 ((unsigned char) (packetlen >> 16) & 0xff));
5102
5103 curproxy->check_req[3] = 1;
5104 curproxy->check_req[5] = 128;
5105 curproxy->check_req[8] = 1;
5106 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5107 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5108 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5109 cur_arg += 2;
5110 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005111 } else {
5112 /* unknown suboption - catchall */
5113 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5114 file, linenum, args[0], args[1]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118 } /* end while loop */
5119 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005120 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005121 else if (!strcmp(args[1], "ldap-check")) {
5122 /* use LDAP request to check servers' health */
5123 free(curproxy->check_req);
5124 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005125 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005126 curproxy->options2 |= PR_O2_LDAP_CHK;
5127
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005128 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005129 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5130 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005131 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5132 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005133 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005134 else if (!strcmp(args[1], "spop-check")) {
5135 if (curproxy == &defproxy) {
5136 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5137 file, linenum, args[0], args[1]);
5138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
5140 }
5141 if (curproxy->cap & PR_CAP_FE) {
5142 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5143 file, linenum, args[0], args[1]);
5144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
5146 }
5147
5148 /* use SPOE request to check servers' health */
5149 free(curproxy->check_req);
5150 curproxy->check_req = NULL;
5151 curproxy->options2 &= ~PR_O2_CHK_ANY;
5152 curproxy->options2 |= PR_O2_SPOP_CHK;
5153
Christopher Faulet8ef75252017-02-20 22:56:03 +01005154 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005155 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
5158 }
5159 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5160 goto out;
5161 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005162 else if (!strcmp(args[1], "tcp-check")) {
5163 /* use raw TCPCHK send/expect to check servers' health */
5164 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5165 err_code |= ERR_WARN;
5166
5167 free(curproxy->check_req);
5168 curproxy->check_req = NULL;
5169 curproxy->options2 &= ~PR_O2_CHK_ANY;
5170 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005171 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5172 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005173 }
Simon Horman98637e52014-06-20 12:30:16 +09005174 else if (!strcmp(args[1], "external-check")) {
5175 /* excute an external command to check servers' health */
5176 free(curproxy->check_req);
5177 curproxy->check_req = NULL;
5178 curproxy->options2 &= ~PR_O2_CHK_ANY;
5179 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005180 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5181 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005182 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005183 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005184 int cur_arg;
5185
5186 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5187 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005188 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005189
Willy Tarreau87cf5142011-08-19 22:57:24 +02005190 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005191
5192 free(curproxy->fwdfor_hdr_name);
5193 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5194 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5195
5196 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5197 cur_arg = 2;
5198 while (*(args[cur_arg])) {
5199 if (!strcmp(args[cur_arg], "except")) {
5200 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005201 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005202 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5203 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005206 }
5207 /* flush useless bits */
5208 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005209 cur_arg += 2;
5210 } else if (!strcmp(args[cur_arg], "header")) {
5211 /* suboption header - needs additional argument for it */
5212 if (*(args[cur_arg+1]) == 0) {
5213 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5214 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005217 }
5218 free(curproxy->fwdfor_hdr_name);
5219 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5220 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5221 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005222 } else if (!strcmp(args[cur_arg], "if-none")) {
5223 curproxy->options &= ~PR_O_FF_ALWAYS;
5224 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005225 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005226 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005227 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005228 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005231 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005232 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005233 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005234 else if (!strcmp(args[1], "originalto")) {
5235 int cur_arg;
5236
5237 /* insert x-original-to field, but not for the IP address listed as an except.
5238 * set default options (ie: bitfield, header name, etc)
5239 */
5240
5241 curproxy->options |= PR_O_ORGTO;
5242
5243 free(curproxy->orgto_hdr_name);
5244 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5245 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5246
Willy Tarreau87cf5142011-08-19 22:57:24 +02005247 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005248 cur_arg = 2;
5249 while (*(args[cur_arg])) {
5250 if (!strcmp(args[cur_arg], "except")) {
5251 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005252 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 +02005253 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5254 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005257 }
5258 /* flush useless bits */
5259 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5260 cur_arg += 2;
5261 } else if (!strcmp(args[cur_arg], "header")) {
5262 /* suboption header - needs additional argument for it */
5263 if (*(args[cur_arg+1]) == 0) {
5264 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5265 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005266 err_code |= ERR_ALERT | ERR_FATAL;
5267 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005268 }
5269 free(curproxy->orgto_hdr_name);
5270 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5271 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5272 cur_arg += 2;
5273 } else {
5274 /* unknown suboption - catchall */
5275 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5276 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005279 }
5280 } /* end while loop */
5281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 else {
5283 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005284 err_code |= ERR_ALERT | ERR_FATAL;
5285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
Willy Tarreau93893792009-07-23 13:19:11 +02005287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005289 else if (!strcmp(args[0], "default_backend")) {
5290 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005292
5293 if (*(args[1]) == 0) {
5294 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005297 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005298 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005299 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005300
5301 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5302 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005305 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005307
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005308 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5309 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 +01005310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005311 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 /* enable reconnections to dispatch */
5313 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005314
5315 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005318 else if (!strcmp(args[0], "http-reuse")) {
5319 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5320 err_code |= ERR_WARN;
5321
5322 if (strcmp(args[1], "never") == 0) {
5323 /* enable a graceful server shutdown on an HTTP 404 response */
5324 curproxy->options &= ~PR_O_REUSE_MASK;
5325 curproxy->options |= PR_O_REUSE_NEVR;
5326 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5327 goto out;
5328 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005329 else if (strcmp(args[1], "safe") == 0) {
5330 /* enable a graceful server shutdown on an HTTP 404 response */
5331 curproxy->options &= ~PR_O_REUSE_MASK;
5332 curproxy->options |= PR_O_REUSE_SAFE;
5333 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5334 goto out;
5335 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005336 else if (strcmp(args[1], "aggressive") == 0) {
5337 curproxy->options &= ~PR_O_REUSE_MASK;
5338 curproxy->options |= PR_O_REUSE_AGGR;
5339 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5340 goto out;
5341 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005342 else if (strcmp(args[1], "always") == 0) {
5343 /* enable a graceful server shutdown on an HTTP 404 response */
5344 curproxy->options &= ~PR_O_REUSE_MASK;
5345 curproxy->options |= PR_O_REUSE_ALWS;
5346 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5347 goto out;
5348 }
5349 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005350 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
5354 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005355 else if (!strcmp(args[0], "http-check")) {
5356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005357 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005358
5359 if (strcmp(args[1], "disable-on-404") == 0) {
5360 /* enable a graceful server shutdown on an HTTP 404 response */
5361 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005362 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5363 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005364 }
Willy Tarreauef781042010-01-27 11:53:01 +01005365 else if (strcmp(args[1], "send-state") == 0) {
5366 /* enable emission of the apparent state of a server in HTTP checks */
5367 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005368 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5369 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005370 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005371 else if (strcmp(args[1], "expect") == 0) {
5372 const char *ptr_arg;
5373 int cur_arg;
5374
5375 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5376 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
5379 }
5380
5381 cur_arg = 2;
5382 /* consider exclamation marks, sole or at the beginning of a word */
5383 while (*(ptr_arg = args[cur_arg])) {
5384 while (*ptr_arg == '!') {
5385 curproxy->options2 ^= PR_O2_EXP_INV;
5386 ptr_arg++;
5387 }
5388 if (*ptr_arg)
5389 break;
5390 cur_arg++;
5391 }
5392 /* now ptr_arg points to the beginning of a word past any possible
5393 * exclamation mark, and cur_arg is the argument which holds this word.
5394 */
5395 if (strcmp(ptr_arg, "status") == 0) {
5396 if (!*(args[cur_arg + 1])) {
5397 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5398 file, linenum, args[0], args[1], ptr_arg);
5399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
5402 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005403 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005404 curproxy->expect_str = strdup(args[cur_arg + 1]);
5405 }
5406 else if (strcmp(ptr_arg, "string") == 0) {
5407 if (!*(args[cur_arg + 1])) {
5408 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5409 file, linenum, args[0], args[1], ptr_arg);
5410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
5413 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005414 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005415 curproxy->expect_str = strdup(args[cur_arg + 1]);
5416 }
5417 else if (strcmp(ptr_arg, "rstatus") == 0) {
5418 if (!*(args[cur_arg + 1])) {
5419 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5420 file, linenum, args[0], args[1], ptr_arg);
5421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
5423 }
5424 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005425 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005426 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005427 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005428 free(curproxy->expect_regex);
5429 curproxy->expect_regex = NULL;
5430 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005431 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005432 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5433 error = NULL;
5434 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5435 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5436 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5437 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
5441 }
5442 else if (strcmp(ptr_arg, "rstring") == 0) {
5443 if (!*(args[cur_arg + 1])) {
5444 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5445 file, linenum, args[0], args[1], ptr_arg);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
5449 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005450 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005451 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005452 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005453 free(curproxy->expect_regex);
5454 curproxy->expect_regex = NULL;
5455 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005456 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005457 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5458 error = NULL;
5459 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5460 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5461 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5462 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
5465 }
5466 }
5467 else {
5468 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5469 file, linenum, args[0], args[1], ptr_arg);
5470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
5472 }
5473 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005474 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005475 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 +02005476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005478 }
5479 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005480 else if (!strcmp(args[0], "tcp-check")) {
5481 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5482 err_code |= ERR_WARN;
5483
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005484 if (strcmp(args[1], "comment") == 0) {
5485 int cur_arg;
5486 struct tcpcheck_rule *tcpcheck;
5487
5488 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005489 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005490 tcpcheck->action = TCPCHK_ACT_COMMENT;
5491
5492 if (!*args[cur_arg + 1]) {
5493 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5494 file, linenum, args[cur_arg]);
5495 err_code |= ERR_ALERT | ERR_FATAL;
5496 goto out;
5497 }
5498
5499 tcpcheck->comment = strdup(args[cur_arg + 1]);
5500
5501 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005502 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5503 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005504 }
5505 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005506 const char *ptr_arg;
5507 int cur_arg;
5508 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005509
5510 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005511 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5512 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5513 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5514 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5515 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005516
Willy Tarreau5581c272015-05-13 12:24:53 +02005517 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5518 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5519 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5520 file, linenum);
5521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005523 }
5524
5525 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005526 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005527 tcpcheck->action = TCPCHK_ACT_CONNECT;
5528
5529 /* parsing each parameters to fill up the rule */
5530 while (*(ptr_arg = args[cur_arg])) {
5531 /* tcp port */
5532 if (strcmp(args[cur_arg], "port") == 0) {
5533 if ( (atol(args[cur_arg + 1]) > 65535) ||
5534 (atol(args[cur_arg + 1]) < 1) ){
5535 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5536 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5537 err_code |= ERR_ALERT | ERR_FATAL;
5538 goto out;
5539 }
5540 tcpcheck->port = atol(args[cur_arg + 1]);
5541 cur_arg += 2;
5542 }
5543 /* send proxy protocol */
5544 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5545 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5546 cur_arg++;
5547 }
5548#ifdef USE_OPENSSL
5549 else if (strcmp(args[cur_arg], "ssl") == 0) {
5550 curproxy->options |= PR_O_TCPCHK_SSL;
5551 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5552 cur_arg++;
5553 }
5554#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005555 /* comment for this tcpcheck line */
5556 else if (strcmp(args[cur_arg], "comment") == 0) {
5557 if (!*args[cur_arg + 1]) {
5558 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5559 file, linenum, args[cur_arg]);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563 tcpcheck->comment = strdup(args[cur_arg + 1]);
5564 cur_arg += 2;
5565 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005566 else {
5567#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005568 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 +01005569#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005570 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 +01005571#endif /* USE_OPENSSL */
5572 file, linenum, args[0], args[1], args[cur_arg]);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
5576
5577 }
5578
5579 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5580 }
5581 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005582 if (! *(args[2]) ) {
5583 /* SEND string expected */
5584 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5585 file, linenum, args[0], args[1], args[2]);
5586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
5588 } else {
5589 struct tcpcheck_rule *tcpcheck;
5590
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005591 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005592
5593 tcpcheck->action = TCPCHK_ACT_SEND;
5594 tcpcheck->string_len = strlen(args[2]);
5595 tcpcheck->string = strdup(args[2]);
5596 tcpcheck->expect_regex = NULL;
5597
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005598 /* comment for this tcpcheck line */
5599 if (strcmp(args[3], "comment") == 0) {
5600 if (!*args[4]) {
5601 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5602 file, linenum, args[3]);
5603 err_code |= ERR_ALERT | ERR_FATAL;
5604 goto out;
5605 }
5606 tcpcheck->comment = strdup(args[4]);
5607 }
5608
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005609 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5610 }
5611 }
5612 else if (strcmp(args[1], "send-binary") == 0) {
5613 if (! *(args[2]) ) {
5614 /* SEND binary string expected */
5615 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5616 file, linenum, args[0], args[1], args[2]);
5617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
5619 } else {
5620 struct tcpcheck_rule *tcpcheck;
5621 char *err = NULL;
5622
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005623 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005624
5625 tcpcheck->action = TCPCHK_ACT_SEND;
5626 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5627 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5628 file, linenum, args[0], args[1], args[2], err);
5629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
5631 }
5632 tcpcheck->expect_regex = NULL;
5633
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005634 /* comment for this tcpcheck line */
5635 if (strcmp(args[3], "comment") == 0) {
5636 if (!*args[4]) {
5637 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5638 file, linenum, args[3]);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
5642 tcpcheck->comment = strdup(args[4]);
5643 }
5644
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005645 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5646 }
5647 }
5648 else if (strcmp(args[1], "expect") == 0) {
5649 const char *ptr_arg;
5650 int cur_arg;
5651 int inverse = 0;
5652
5653 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5654 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
5657 }
5658
5659 cur_arg = 2;
5660 /* consider exclamation marks, sole or at the beginning of a word */
5661 while (*(ptr_arg = args[cur_arg])) {
5662 while (*ptr_arg == '!') {
5663 inverse = !inverse;
5664 ptr_arg++;
5665 }
5666 if (*ptr_arg)
5667 break;
5668 cur_arg++;
5669 }
5670 /* now ptr_arg points to the beginning of a word past any possible
5671 * exclamation mark, and cur_arg is the argument which holds this word.
5672 */
5673 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005674 struct tcpcheck_rule *tcpcheck;
5675 char *err = NULL;
5676
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005677 if (!*(args[cur_arg + 1])) {
5678 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5679 file, linenum, args[0], args[1], ptr_arg);
5680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005683
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005684 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005685
5686 tcpcheck->action = TCPCHK_ACT_EXPECT;
5687 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5688 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5689 file, linenum, args[0], args[1], args[2], err);
5690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
5692 }
5693 tcpcheck->expect_regex = NULL;
5694 tcpcheck->inverse = inverse;
5695
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005696 /* tcpcheck comment */
5697 cur_arg += 2;
5698 if (strcmp(args[cur_arg], "comment") == 0) {
5699 if (!*args[cur_arg + 1]) {
5700 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5701 file, linenum, args[cur_arg + 1]);
5702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
5705 tcpcheck->comment = strdup(args[cur_arg + 1]);
5706 }
5707
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005708 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5709 }
5710 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005711 struct tcpcheck_rule *tcpcheck;
5712
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005713 if (!*(args[cur_arg + 1])) {
5714 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5715 file, linenum, args[0], args[1], ptr_arg);
5716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
5718 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005719
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005720 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005721
5722 tcpcheck->action = TCPCHK_ACT_EXPECT;
5723 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5724 tcpcheck->string = strdup(args[cur_arg + 1]);
5725 tcpcheck->expect_regex = NULL;
5726 tcpcheck->inverse = inverse;
5727
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005728 /* tcpcheck comment */
5729 cur_arg += 2;
5730 if (strcmp(args[cur_arg], "comment") == 0) {
5731 if (!*args[cur_arg + 1]) {
5732 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5733 file, linenum, args[cur_arg + 1]);
5734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
5736 }
5737 tcpcheck->comment = strdup(args[cur_arg + 1]);
5738 }
5739
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005740 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5741 }
5742 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005743 struct tcpcheck_rule *tcpcheck;
5744
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005745 if (!*(args[cur_arg + 1])) {
5746 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5747 file, linenum, args[0], args[1], ptr_arg);
5748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
5750 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005751
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005752 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005753
5754 tcpcheck->action = TCPCHK_ACT_EXPECT;
5755 tcpcheck->string_len = 0;
5756 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005757 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5758 error = NULL;
5759 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5760 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5761 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5762 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
5765 }
5766 tcpcheck->inverse = inverse;
5767
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005768 /* tcpcheck comment */
5769 cur_arg += 2;
5770 if (strcmp(args[cur_arg], "comment") == 0) {
5771 if (!*args[cur_arg + 1]) {
5772 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5773 file, linenum, args[cur_arg + 1]);
5774 err_code |= ERR_ALERT | ERR_FATAL;
5775 goto out;
5776 }
5777 tcpcheck->comment = strdup(args[cur_arg + 1]);
5778 }
5779
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005780 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5781 }
5782 else {
5783 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5784 file, linenum, args[0], args[1], ptr_arg);
5785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
5787 }
5788 }
5789 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005790 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005791 err_code |= ERR_ALERT | ERR_FATAL;
5792 goto out;
5793 }
5794 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005795 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005796 if (curproxy == &defproxy) {
5797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005800 }
5801
Willy Tarreaub80c2302007-11-30 20:51:32 +01005802 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005803 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005804
5805 if (strcmp(args[1], "fail") == 0) {
5806 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005807 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005808 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5809 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005810 err_code |= ERR_ALERT | ERR_FATAL;
5811 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005812 }
5813
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005814 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005815 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5816 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005819 }
5820 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5821 }
5822 else {
5823 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005824 err_code |= ERR_ALERT | ERR_FATAL;
5825 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005826 }
5827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828#ifdef TPROXY
5829 else if (!strcmp(args[0], "transparent")) {
5830 /* enable transparent proxy connections */
5831 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005832 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 }
5835#endif
5836 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005837 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005838 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005839
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 if (*(args[1]) == 0) {
5841 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844 }
5845 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005846 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005849 else if (!strcmp(args[0], "backlog")) { /* backlog */
5850 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005851 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005852
5853 if (*(args[1]) == 0) {
5854 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005855 err_code |= ERR_ALERT | ERR_FATAL;
5856 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005857 }
5858 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005859 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5860 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005861 }
Willy Tarreau86034312006-12-29 00:10:33 +01005862 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005864 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005865
Willy Tarreau86034312006-12-29 00:10:33 +01005866 if (*(args[1]) == 0) {
5867 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005870 }
5871 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005872 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5873 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005874 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005875 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5876 if (*(args[1]) == 0) {
5877 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005878 err_code |= ERR_ALERT | ERR_FATAL;
5879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005881 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5882 if (err) {
5883 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5884 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005887 }
5888 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005889 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
5892 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005893 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005894 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005895 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005896
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 if (curproxy == &defproxy) {
5898 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005902 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005903 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005904
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005905 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005906 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005907 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005908 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005909 goto out;
5910 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005911
5912 proto = protocol_by_family(sk->ss_family);
5913 if (!proto || !proto->connect) {
5914 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5915 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005916 err_code |= ERR_ALERT | ERR_FATAL;
5917 goto out;
5918 }
5919
5920 if (port1 != port2) {
5921 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5922 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005923 err_code |= ERR_ALERT | ERR_FATAL;
5924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005926
5927 if (!port1) {
5928 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5929 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005933
William Lallemanddf1425a2015-04-28 20:17:49 +02005934 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5935 goto out;
5936
Willy Tarreaud5191e72010-02-09 20:50:45 +01005937 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005938 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939 }
5940 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005941 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005942 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005943
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005944 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5945 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005946 err_code |= ERR_ALERT | ERR_FATAL;
5947 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005950 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005951 /**
5952 * The syntax for hash-type config element is
5953 * hash-type {map-based|consistent} [[<algo>] avalanche]
5954 *
5955 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5956 */
5957 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005958
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5960 err_code |= ERR_WARN;
5961
5962 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005963 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5964 }
5965 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005966 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5967 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005968 else if (strcmp(args[1], "avalanche") == 0) {
5969 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]);
5970 err_code |= ERR_ALERT | ERR_FATAL;
5971 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005972 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005973 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005974 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005975 err_code |= ERR_ALERT | ERR_FATAL;
5976 goto out;
5977 }
Bhaskar98634f02013-10-29 23:30:51 -04005978
5979 /* set the hash function to use */
5980 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005981 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005982 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005983
5984 /* if consistent with no argument, then avalanche modifier is also applied */
5985 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5986 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005987 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005988 /* set the hash function */
5989 if (!strcmp(args[2], "sdbm")) {
5990 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5991 }
5992 else if (!strcmp(args[2], "djb2")) {
5993 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005994 }
5995 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005996 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005997 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005998 else if (!strcmp(args[2], "crc32")) {
5999 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
6000 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05006001 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01006002 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 -05006003 err_code |= ERR_ALERT | ERR_FATAL;
6004 goto out;
6005 }
6006
6007 /* set the hash modifier */
6008 if (!strcmp(args[3], "avalanche")) {
6009 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
6010 }
6011 else if (*args[3]) {
6012 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
6013 err_code |= ERR_ALERT | ERR_FATAL;
6014 goto out;
6015 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01006016 }
William Lallemanda73203e2012-03-12 12:48:57 +01006017 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04006018 else if (strcmp(args[0], "hash-balance-factor") == 0) {
6019 if (*(args[1]) == 0) {
6020 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
6021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
6023 }
6024 curproxy->lbprm.chash.balance_factor = atol(args[1]);
6025 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
6026 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
6027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
6029 }
6030 }
William Lallemanda73203e2012-03-12 12:48:57 +01006031 else if (strcmp(args[0], "unique-id-format") == 0) {
6032 if (!*(args[1])) {
6033 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6034 err_code |= ERR_ALERT | ERR_FATAL;
6035 goto out;
6036 }
William Lallemand3203ff42012-11-11 17:30:56 +01006037 if (*(args[2])) {
6038 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6039 err_code |= ERR_ALERT | ERR_FATAL;
6040 goto out;
6041 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006042 free(curproxy->conf.uniqueid_format_string);
6043 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006044
Willy Tarreau62a61232013-04-12 18:13:46 +02006045 free(curproxy->conf.uif_file);
6046 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6047 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006048 }
William Lallemanda73203e2012-03-12 12:48:57 +01006049
6050 else if (strcmp(args[0], "unique-id-header") == 0) {
6051 if (!*(args[1])) {
6052 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6053 err_code |= ERR_ALERT | ERR_FATAL;
6054 goto out;
6055 }
6056 free(curproxy->header_unique_id);
6057 curproxy->header_unique_id = strdup(args[1]);
6058 }
6059
William Lallemand723b73a2012-02-08 16:37:49 +01006060 else if (strcmp(args[0], "log-format") == 0) {
6061 if (!*(args[1])) {
6062 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6063 err_code |= ERR_ALERT | ERR_FATAL;
6064 goto out;
6065 }
William Lallemand3203ff42012-11-11 17:30:56 +01006066 if (*(args[2])) {
6067 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006071 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
6072 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02006073
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006074 if (curproxy->conf.logformat_string == default_http_log_format)
6075 oldlogformat = "option httplog";
6076 else if (curproxy->conf.logformat_string == default_tcp_log_format)
6077 oldlogformat = "option tcplog";
6078 else if (curproxy->conf.logformat_string == clf_http_log_format)
6079 oldlogformat = "option httplog clf";
6080 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
6081 file, linenum, oldlogformat);
6082 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006083 if (curproxy->conf.logformat_string != default_http_log_format &&
6084 curproxy->conf.logformat_string != default_tcp_log_format &&
6085 curproxy->conf.logformat_string != clf_http_log_format)
6086 free(curproxy->conf.logformat_string);
6087 curproxy->conf.logformat_string = strdup(args[1]);
6088
6089 free(curproxy->conf.lfs_file);
6090 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6091 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006092
6093 /* get a chance to improve log-format error reporting by
6094 * reporting the correct line-number when possible.
6095 */
6096 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6097 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6098 file, linenum, curproxy->id);
6099 err_code |= ERR_WARN;
6100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006102 else if (!strcmp(args[0], "log-format-sd")) {
6103 if (!*(args[1])) {
6104 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6105 err_code |= ERR_ALERT | ERR_FATAL;
6106 goto out;
6107 }
6108 if (*(args[2])) {
6109 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
6112 }
6113
6114 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6115 free(curproxy->conf.logformat_sd_string);
6116 curproxy->conf.logformat_sd_string = strdup(args[1]);
6117
6118 free(curproxy->conf.lfsd_file);
6119 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6120 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6121
6122 /* get a chance to improve log-format-sd error reporting by
6123 * reporting the correct line-number when possible.
6124 */
6125 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6126 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6127 file, linenum, curproxy->id);
6128 err_code |= ERR_WARN;
6129 }
6130 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006131 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6132 if (*(args[1]) == 0) {
6133 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6134 err_code |= ERR_ALERT | ERR_FATAL;
6135 goto out;
6136 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006137 chunk_destroy(&curproxy->log_tag);
6138 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006139 }
William Lallemand0f99e342011-10-12 17:50:54 +02006140 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6141 /* delete previous herited or defined syslog servers */
6142 struct logsrv *back;
6143
6144 if (*(args[1]) != 0) {
6145 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6146 err_code |= ERR_ALERT | ERR_FATAL;
6147 goto out;
6148 }
6149
William Lallemand723b73a2012-02-08 16:37:49 +01006150 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6151 LIST_DEL(&tmplogsrv->list);
6152 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006153 }
6154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006156 struct logsrv *logsrv;
6157
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006159 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006160 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006161 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006162 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006163 LIST_INIT(&node->list);
6164 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6165 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 }
6167 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006168 struct sockaddr_storage *sk;
6169 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006170 int arg = 0;
6171 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006172
Vincent Bernat02779b62016-04-03 13:48:43 +02006173 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174
Willy Tarreau18324f52014-06-27 18:10:07 +02006175 /* just after the address, a length may be specified */
6176 if (strcmp(args[arg+2], "len") == 0) {
6177 len = atoi(args[arg+3]);
6178 if (len < 80 || len > 65535) {
6179 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6180 file, linenum, args[arg+3]);
6181 err_code |= ERR_ALERT | ERR_FATAL;
6182 goto out;
6183 }
6184 logsrv->maxlen = len;
6185
6186 /* skip these two args */
6187 arg += 2;
6188 }
6189 else
6190 logsrv->maxlen = MAX_SYSLOG_LEN;
6191
Christopher Faulet084aa962017-08-29 16:54:41 +02006192 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006193 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006194
Dragan Dosen1322d092015-09-22 16:05:32 +02006195 /* after the length, a format may be specified */
6196 if (strcmp(args[arg+2], "format") == 0) {
6197 logsrv->format = get_log_format(args[arg+3]);
6198 if (logsrv->format < 0) {
6199 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
6202 }
6203
6204 /* skip these two args */
6205 arg += 2;
6206 }
6207
William Lallemanddf1425a2015-04-28 20:17:49 +02006208 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6209 goto out;
6210
Willy Tarreau18324f52014-06-27 18:10:07 +02006211 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006212 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006213 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006214 err_code |= ERR_ALERT | ERR_FATAL;
6215 goto out;
6216
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 }
6218
William Lallemand0f99e342011-10-12 17:50:54 +02006219 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006220 if (*(args[arg+3])) {
6221 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006222 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006223 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
6226
Willy Tarreaubaaee002006-06-26 02:48:02 +02006227 }
6228 }
6229
William Lallemand0f99e342011-10-12 17:50:54 +02006230 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006231 if (*(args[arg+4])) {
6232 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006233 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006234 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
6237
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006238 }
6239 }
6240
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006241 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006242 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006243 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006244 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006245 goto out;
6246 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006247
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006248 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006249
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006250 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006251 if (port1 != port2) {
6252 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6253 file, linenum, args[0], args[1]);
6254 err_code |= ERR_ALERT | ERR_FATAL;
6255 goto out;
6256 }
6257
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006258 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006259 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
William Lallemand0f99e342011-10-12 17:50:54 +02006261
6262 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006263 }
6264 else {
6265 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6266 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006267 err_code |= ERR_ALERT | ERR_FATAL;
6268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 }
6270 }
6271 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006272 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006273 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006274 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006275 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006276
Willy Tarreau977b8e42006-12-29 14:19:17 +01006277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006278 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006279
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006281 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6282 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006283 err_code |= ERR_ALERT | ERR_FATAL;
6284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006285 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006286
6287 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006288 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6289 free(curproxy->conn_src.iface_name);
6290 curproxy->conn_src.iface_name = NULL;
6291 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006292
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006293 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006294 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006295 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006296 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006297 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006298 goto out;
6299 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006300
6301 proto = protocol_by_family(sk->ss_family);
6302 if (!proto || !proto->connect) {
6303 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006304 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006305 err_code |= ERR_ALERT | ERR_FATAL;
6306 goto out;
6307 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006308
6309 if (port1 != port2) {
6310 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6311 file, linenum, args[0], args[1]);
6312 err_code |= ERR_ALERT | ERR_FATAL;
6313 goto out;
6314 }
6315
Willy Tarreauef9a3602012-12-08 22:29:20 +01006316 curproxy->conn_src.source_addr = *sk;
6317 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006318
6319 cur_arg = 2;
6320 while (*(args[cur_arg])) {
6321 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006322#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006323 if (!*args[cur_arg + 1]) {
6324 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6325 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006326 err_code |= ERR_ALERT | ERR_FATAL;
6327 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006328 }
6329
6330 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006331 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6332 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006333 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006334 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6335 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006336 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6337 char *name, *end;
6338
6339 name = args[cur_arg+1] + 7;
6340 while (isspace(*name))
6341 name++;
6342
6343 end = name;
6344 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6345 end++;
6346
Willy Tarreauef9a3602012-12-08 22:29:20 +01006347 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6348 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6349 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6350 curproxy->conn_src.bind_hdr_len = end - name;
6351 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6352 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6353 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006354
6355 /* now look for an occurrence number */
6356 while (isspace(*end))
6357 end++;
6358 if (*end == ',') {
6359 end++;
6360 name = end;
6361 if (*end == '-')
6362 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006363 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006364 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006365 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006366 }
6367
Willy Tarreauef9a3602012-12-08 22:29:20 +01006368 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006369 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6370 " occurrences values smaller than %d.\n",
6371 file, linenum, MAX_HDR_HISTORY);
6372 err_code |= ERR_ALERT | ERR_FATAL;
6373 goto out;
6374 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006375 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006376 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006377
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006378 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006379 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006380 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006381 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006383 goto out;
6384 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006385
6386 proto = protocol_by_family(sk->ss_family);
6387 if (!proto || !proto->connect) {
6388 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6389 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006390 err_code |= ERR_ALERT | ERR_FATAL;
6391 goto out;
6392 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006393
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006394 if (port1 != port2) {
6395 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6396 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006397 err_code |= ERR_ALERT | ERR_FATAL;
6398 goto out;
6399 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006400 curproxy->conn_src.tproxy_addr = *sk;
6401 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006402 }
6403 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006404#else /* no TPROXY support */
6405 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006406 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006407 err_code |= ERR_ALERT | ERR_FATAL;
6408 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006409#endif
6410 cur_arg += 2;
6411 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006412 }
6413
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006414 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6415#ifdef SO_BINDTODEVICE
6416 if (!*args[cur_arg + 1]) {
6417 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006419 err_code |= ERR_ALERT | ERR_FATAL;
6420 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006421 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006422 free(curproxy->conn_src.iface_name);
6423 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6424 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006425 global.last_checks |= LSTCHK_NETADM;
6426#else
6427 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6428 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006429 err_code |= ERR_ALERT | ERR_FATAL;
6430 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006431#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006432 cur_arg += 2;
6433 continue;
6434 }
6435 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006436 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006437 err_code |= ERR_ALERT | ERR_FATAL;
6438 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006441 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6442 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6443 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006444 err_code |= ERR_ALERT | ERR_FATAL;
6445 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006448 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006451 err_code |= ERR_ALERT | ERR_FATAL;
6452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006454
6455 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006456 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006457 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 }
6461 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006463 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006464 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 }
6468 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006469 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006470 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006471 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006472 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 }
6475 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006476 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006477 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006478 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 }
6482 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006484 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006485 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006489 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006491 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006492 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006494 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006496 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006497 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6499 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006500 err_code |= ERR_ALERT | ERR_FATAL;
6501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503
6504 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006505 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006506 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006511 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006512 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006513 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006514 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 }
6517 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006518 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006519 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006520 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006521 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
6524 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006525 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006526 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006527 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006528 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 }
6531 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006532 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006533 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006534 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006535 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006538 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006539 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006540 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006541 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006542 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006543 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006544 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006546 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006547
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548 if (curproxy == &defproxy) {
6549 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006550 err_code |= ERR_ALERT | ERR_FATAL;
6551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006553 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006554 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556 if (*(args[1]) == 0) {
6557 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006561
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006562 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006563 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006564 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6565 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006566 err_code |= ERR_ALERT | ERR_FATAL;
6567 goto out;
6568 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006569 err_code |= warnif_cond_conflicts(cond,
6570 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6571 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006572 }
6573 else if (*args[2]) {
6574 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6575 file, linenum, args[0], args[2]);
6576 err_code |= ERR_ALERT | ERR_FATAL;
6577 goto out;
6578 }
6579
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006580 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006581 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006582 wl->s = strdup(args[1]);
6583 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006584 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585 }
6586 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006587 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6589 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006590 err_code |= ERR_ALERT | ERR_FATAL;
6591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006593
Willy Tarreauade5ec42010-01-28 19:33:49 +01006594 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006595 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006596 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006597 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599 }
6600 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006601 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006602 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006603 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006604 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606 }
6607 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006608 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006609 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006610 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006611 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 }
6614 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006615 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6617 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006618 err_code |= ERR_ALERT | ERR_FATAL;
6619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006620 }
6621
Willy Tarreauade5ec42010-01-28 19:33:49 +01006622 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006623 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006624 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006625 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006627 }
6628 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006629 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006630 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006631 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006632 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006634 }
6635 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006636 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006637 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006638 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006639 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006641 }
6642 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006643 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006644
Willy Tarreaubaaee002006-06-26 02:48:02 +02006645 if (curproxy == &defproxy) {
6646 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006647 err_code |= ERR_ALERT | ERR_FATAL;
6648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006649 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006650 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006651 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006652
Willy Tarreaubaaee002006-06-26 02:48:02 +02006653 if (*(args[1]) == 0) {
6654 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 }
6658
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006659 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006660 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006661 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6662 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006663 err_code |= ERR_ALERT | ERR_FATAL;
6664 goto out;
6665 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006666 err_code |= warnif_cond_conflicts(cond,
6667 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6668 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006669 }
6670 else if (*args[2]) {
6671 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6672 file, linenum, args[0], args[2]);
6673 err_code |= ERR_ALERT | ERR_FATAL;
6674 goto out;
6675 }
6676
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006677 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006678 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006679 wl->s = strdup(args[1]);
6680 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006681 }
6682 else if (!strcmp(args[0], "errorloc") ||
6683 !strcmp(args[0], "errorloc302") ||
6684 !strcmp(args[0], "errorloc303")) { /* error location */
6685 int errnum, errlen;
6686 char *err;
6687
Willy Tarreau977b8e42006-12-29 14:19:17 +01006688 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006689 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006690
Willy Tarreaubaaee002006-06-26 02:48:02 +02006691 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006692 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006693 err_code |= ERR_ALERT | ERR_FATAL;
6694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006695 }
6696
6697 errnum = atol(args[1]);
6698 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006699 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6700 err = malloc(errlen);
6701 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006702 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006703 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6704 err = malloc(errlen);
6705 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006706 }
6707
Willy Tarreau0f772532006-12-23 20:51:41 +01006708 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6709 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006710 chunk_destroy(&curproxy->errmsg[rc]);
6711 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006712 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006714 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006715
6716 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006717 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6718 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006719 free(err);
6720 }
6721 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006722 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6723 int errnum, errlen, fd;
6724 char *err;
6725 struct stat stat;
6726
6727 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006728 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006729
6730 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006731 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006732 err_code |= ERR_ALERT | ERR_FATAL;
6733 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006734 }
6735
6736 fd = open(args[2], O_RDONLY);
6737 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6738 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6739 file, linenum, args[2], args[1]);
6740 if (fd >= 0)
6741 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006742 err_code |= ERR_ALERT | ERR_FATAL;
6743 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006744 }
6745
Willy Tarreau27a674e2009-08-17 07:23:33 +02006746 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006747 errlen = stat.st_size;
6748 } else {
6749 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006750 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006751 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006752 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006753 }
6754
6755 err = malloc(errlen); /* malloc() must succeed during parsing */
6756 errnum = read(fd, err, errlen);
6757 if (errnum != errlen) {
6758 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6759 file, linenum, args[2], args[1]);
6760 close(fd);
6761 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006762 err_code |= ERR_ALERT | ERR_FATAL;
6763 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006764 }
6765 close(fd);
6766
6767 errnum = atol(args[1]);
6768 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6769 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006770 chunk_destroy(&curproxy->errmsg[rc]);
6771 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006772 break;
6773 }
6774 }
6775
6776 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006777 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6778 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006779 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006780 free(err);
6781 }
6782 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006783 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006784 struct cfg_kw_list *kwl;
6785 int index;
6786
6787 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6788 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6789 if (kwl->kw[index].section != CFG_LISTEN)
6790 continue;
6791 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6792 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006793 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006794 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006795 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006796 err_code |= ERR_ALERT | ERR_FATAL;
6797 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006798 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006799 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006800 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006801 err_code |= ERR_WARN;
6802 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006803 }
Willy Tarreau93893792009-07-23 13:19:11 +02006804 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006805 }
6806 }
6807 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006808
Willy Tarreau6daf3432008-01-22 16:44:08 +01006809 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006810 err_code |= ERR_ALERT | ERR_FATAL;
6811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006812 }
Willy Tarreau93893792009-07-23 13:19:11 +02006813 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006814 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006815 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006816}
6817
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006818int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006819cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6820{
6821#ifdef CONFIG_HAP_NS
6822 const char *err;
6823 const char *item = args[0];
6824
6825 if (!strcmp(item, "namespace_list")) {
6826 return 0;
6827 }
6828 else if (!strcmp(item, "namespace")) {
6829 size_t idx = 1;
6830 const char *current;
6831 while (*(current = args[idx++])) {
6832 err = invalid_char(current);
6833 if (err) {
6834 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6835 file, linenum, *err, item, current);
6836 return ERR_ALERT | ERR_FATAL;
6837 }
6838
6839 if (netns_store_lookup(current, strlen(current))) {
6840 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6841 file, linenum, current);
6842 return ERR_ALERT | ERR_FATAL;
6843 }
6844 if (!netns_store_insert(current)) {
6845 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6846 file, linenum, current);
6847 return ERR_ALERT | ERR_FATAL;
6848 }
6849 }
6850 }
6851
6852 return 0;
6853#else
6854 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6855 file, linenum);
6856 return ERR_ALERT | ERR_FATAL;
6857#endif
6858}
6859
6860int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006861cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6862{
6863
6864 int err_code = 0;
6865 const char *err;
6866
6867 if (!strcmp(args[0], "userlist")) { /* new userlist */
6868 struct userlist *newul;
6869
6870 if (!*args[1]) {
6871 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6872 file, linenum, args[0]);
6873 err_code |= ERR_ALERT | ERR_FATAL;
6874 goto out;
6875 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006876 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6877 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006878
6879 err = invalid_char(args[1]);
6880 if (err) {
6881 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6882 file, linenum, *err, args[0], args[1]);
6883 err_code |= ERR_ALERT | ERR_FATAL;
6884 goto out;
6885 }
6886
6887 for (newul = userlist; newul; newul = newul->next)
6888 if (!strcmp(newul->name, args[1])) {
6889 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6890 file, linenum, args[1]);
6891 err_code |= ERR_WARN;
6892 goto out;
6893 }
6894
Vincent Bernat02779b62016-04-03 13:48:43 +02006895 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006896 if (!newul) {
6897 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6898 err_code |= ERR_ALERT | ERR_ABORT;
6899 goto out;
6900 }
6901
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006902 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006903 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006904 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6905 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006906 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006907 goto out;
6908 }
6909
6910 newul->next = userlist;
6911 userlist = newul;
6912
6913 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006914 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006915 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006916 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006917
6918 if (!*args[1]) {
6919 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6920 file, linenum, args[0]);
6921 err_code |= ERR_ALERT | ERR_FATAL;
6922 goto out;
6923 }
6924
6925 err = invalid_char(args[1]);
6926 if (err) {
6927 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6928 file, linenum, *err, args[0], args[1]);
6929 err_code |= ERR_ALERT | ERR_FATAL;
6930 goto out;
6931 }
6932
William Lallemand4ac9f542015-05-28 18:03:51 +02006933 if (!userlist)
6934 goto out;
6935
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006936 for (ag = userlist->groups; ag; ag = ag->next)
6937 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006938 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6939 file, linenum, args[1], userlist->name);
6940 err_code |= ERR_ALERT;
6941 goto out;
6942 }
6943
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006944 ag = calloc(1, sizeof(*ag));
6945 if (!ag) {
6946 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6947 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006948 goto out;
6949 }
6950
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006951 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006952 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006953 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6954 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006955 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006956 goto out;
6957 }
6958
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006959 cur_arg = 2;
6960
6961 while (*args[cur_arg]) {
6962 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006963 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006964 cur_arg += 2;
6965 continue;
6966 } else {
6967 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6968 file, linenum, args[0]);
6969 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006970 free(ag->groupusers);
6971 free(ag->name);
6972 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006973 goto out;
6974 }
6975 }
6976
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006977 ag->next = userlist->groups;
6978 userlist->groups = ag;
6979
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006980 } else if (!strcmp(args[0], "user")) { /* new user */
6981 struct auth_users *newuser;
6982 int cur_arg;
6983
6984 if (!*args[1]) {
6985 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6986 file, linenum, args[0]);
6987 err_code |= ERR_ALERT | ERR_FATAL;
6988 goto out;
6989 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006990 if (!userlist)
6991 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006992
6993 for (newuser = userlist->users; newuser; newuser = newuser->next)
6994 if (!strcmp(newuser->user, args[1])) {
6995 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6996 file, linenum, args[1], userlist->name);
6997 err_code |= ERR_ALERT;
6998 goto out;
6999 }
7000
Vincent Bernat02779b62016-04-03 13:48:43 +02007001 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007002 if (!newuser) {
7003 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
7004 err_code |= ERR_ALERT | ERR_ABORT;
7005 goto out;
7006 }
7007
7008 newuser->user = strdup(args[1]);
7009
7010 newuser->next = userlist->users;
7011 userlist->users = newuser;
7012
7013 cur_arg = 2;
7014
7015 while (*args[cur_arg]) {
7016 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02007017#ifdef CONFIG_HAP_CRYPT
7018 if (!crypt("", args[cur_arg + 1])) {
7019 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
7020 file, linenum, newuser->user);
7021 err_code |= ERR_ALERT | ERR_FATAL;
7022 goto out;
7023 }
7024#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007025 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
7026 file, linenum);
7027 err_code |= ERR_ALERT;
7028#endif
7029 newuser->pass = strdup(args[cur_arg + 1]);
7030 cur_arg += 2;
7031 continue;
7032 } else if (!strcmp(args[cur_arg], "insecure-password")) {
7033 newuser->pass = strdup(args[cur_arg + 1]);
7034 newuser->flags |= AU_O_INSECURE;
7035 cur_arg += 2;
7036 continue;
7037 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007038 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007039 cur_arg += 2;
7040 continue;
7041 } else {
7042 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7043 file, linenum, args[0]);
7044 err_code |= ERR_ALERT | ERR_FATAL;
7045 goto out;
7046 }
7047 }
7048 } else {
7049 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7050 err_code |= ERR_ALERT | ERR_FATAL;
7051 }
7052
7053out:
7054 return err_code;
7055}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007056
Christopher Faulet79bdef32016-11-04 22:36:15 +01007057int
7058cfg_parse_scope(const char *file, int linenum, char *line)
7059{
7060 char *beg, *end, *scope = NULL;
7061 int err_code = 0;
7062 const char *err;
7063
7064 beg = line + 1;
7065 end = strchr(beg, ']');
7066
7067 /* Detect end of scope declaration */
7068 if (!end || end == beg) {
7069 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7070 file, linenum);
7071 err_code |= ERR_ALERT | ERR_FATAL;
7072 goto out;
7073 }
7074
7075 /* Get scope name and check its validity */
7076 scope = my_strndup(beg, end-beg);
7077 err = invalid_char(scope);
7078 if (err) {
7079 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7080 file, linenum, *err);
7081 err_code |= ERR_ALERT | ERR_ABORT;
7082 goto out;
7083 }
7084
7085 /* Be sure to have a scope declaration alone on its line */
7086 line = end+1;
7087 while (isspace((unsigned char)*line))
7088 line++;
7089 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7090 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7091 file, linenum, *line);
7092 err_code |= ERR_ALERT | ERR_ABORT;
7093 goto out;
7094 }
7095
7096 /* We have a valid scope declaration, save it */
7097 free(cfg_scope);
7098 cfg_scope = scope;
7099 scope = NULL;
7100
7101 out:
7102 free(scope);
7103 return err_code;
7104}
7105
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106/*
7107 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007108 * Returns the error code, 0 if OK, or any combination of :
7109 * - ERR_ABORT: must abort ASAP
7110 * - ERR_FATAL: we can continue parsing but not start the service
7111 * - ERR_WARN: a warning has been emitted
7112 * - ERR_ALERT: an alert has been emitted
7113 * Only the two first ones can stop processing, the two others are just
7114 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007115 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007116int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007117{
William Lallemand64e84512015-05-12 14:25:37 +02007118 char *thisline;
7119 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007120 FILE *f;
7121 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007122 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007123 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007124 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007125 int readbytes = 0;
7126
7127 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007128 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007129 return -1;
7130 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007131
David Carlier97880bb2016-04-08 10:35:26 +01007132 if ((f=fopen(file,"r")) == NULL) {
7133 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007134 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007136
William Lallemandb2f07452015-05-12 14:27:13 +02007137next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007138 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007139 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007140 char *end;
7141 char *args[MAX_LINE_ARGS + 1];
7142 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007143 int dquote = 0; /* double quote */
7144 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007145
Willy Tarreaubaaee002006-06-26 02:48:02 +02007146 linenum++;
7147
7148 end = line + strlen(line);
7149
William Lallemand64e84512015-05-12 14:25:37 +02007150 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007151 /* Check if we reached the limit and the last char is not \n.
7152 * Watch out for the last line without the terminating '\n'!
7153 */
William Lallemand64e84512015-05-12 14:25:37 +02007154 char *newline;
7155 int newlinesize = linesize * 2;
7156
7157 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7158 if (newline == NULL) {
7159 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7160 file, linenum);
7161 err_code |= ERR_ALERT | ERR_FATAL;
7162 continue;
7163 }
7164
7165 readbytes = linesize - 1;
7166 linesize = newlinesize;
7167 thisline = newline;
7168 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007169 }
7170
William Lallemand64e84512015-05-12 14:25:37 +02007171 readbytes = 0;
7172
Willy Tarreaubaaee002006-06-26 02:48:02 +02007173 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007174 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007175 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007176
Christopher Faulet79bdef32016-11-04 22:36:15 +01007177
7178 if (*line == '[') {/* This is the begining if a scope */
7179 err_code |= cfg_parse_scope(file, linenum, line);
7180 goto next_line;
7181 }
7182
Willy Tarreaubaaee002006-06-26 02:48:02 +02007183 arg = 0;
7184 args[arg] = line;
7185
7186 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007187 if (*line == '"' && !squote) { /* double quote outside single quotes */
7188 if (dquote)
7189 dquote = 0;
7190 else
7191 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007192 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007193 end--;
7194 }
7195 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7196 if (squote)
7197 squote = 0;
7198 else
7199 squote = 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 == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007204 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7205 * C equivalent value. Other combinations left unchanged (eg: \1).
7206 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007207 int skip = 0;
7208 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7209 *line = line[1];
7210 skip = 1;
7211 }
7212 else if (line[1] == 'r') {
7213 *line = '\r';
7214 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007216 else if (line[1] == 'n') {
7217 *line = '\n';
7218 skip = 1;
7219 }
7220 else if (line[1] == 't') {
7221 *line = '\t';
7222 skip = 1;
7223 }
7224 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007225 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007226 unsigned char hex1, hex2;
7227 hex1 = toupper(line[2]) - '0';
7228 hex2 = toupper(line[3]) - '0';
7229 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7230 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7231 *line = (hex1<<4) + hex2;
7232 skip = 3;
7233 }
7234 else {
7235 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007236 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007237 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007238 } else if (line[1] == '"') {
7239 *line = '"';
7240 skip = 1;
7241 } else if (line[1] == '\'') {
7242 *line = '\'';
7243 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007244 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7245 *line = '$';
7246 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 }
7248 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007249 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007250 end -= skip;
7251 }
7252 line++;
7253 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007254 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007255 /* end of string, end of loop */
7256 *line = 0;
7257 break;
7258 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007259 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007260 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007261 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007262 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007263 line++;
7264 args[++arg] = line;
7265 }
William Lallemandb2f07452015-05-12 14:27:13 +02007266 else if (dquote && *line == '$') {
7267 /* environment variables are evaluated inside double quotes */
7268 char *var_beg;
7269 char *var_end;
7270 char save_char;
7271 char *value;
7272 int val_len;
7273 int newlinesize;
7274 int braces = 0;
7275
7276 var_beg = line + 1;
7277 var_end = var_beg;
7278
7279 if (*var_beg == '{') {
7280 var_beg++;
7281 var_end++;
7282 braces = 1;
7283 }
7284
7285 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7286 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7287 err_code |= ERR_ALERT | ERR_FATAL;
7288 goto next_line; /* skip current line */
7289 }
7290
7291 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7292 var_end++;
7293
7294 save_char = *var_end;
7295 *var_end = '\0';
7296 value = getenv(var_beg);
7297 *var_end = save_char;
7298 val_len = value ? strlen(value) : 0;
7299
7300 if (braces) {
7301 if (*var_end == '}') {
7302 var_end++;
7303 braces = 0;
7304 } else {
7305 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7306 err_code |= ERR_ALERT | ERR_FATAL;
7307 goto next_line; /* skip current line */
7308 }
7309 }
7310
7311 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7312
7313 /* if not enough space in thisline */
7314 if (newlinesize > linesize) {
7315 char *newline;
7316
7317 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7318 if (newline == NULL) {
7319 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7320 err_code |= ERR_ALERT | ERR_FATAL;
7321 goto next_line; /* slip current line */
7322 }
7323 /* recompute pointers if realloc returns a new pointer */
7324 if (newline != thisline) {
7325 int i;
7326 int diff;
7327
7328 for (i = 0; i <= arg; i++) {
7329 diff = args[i] - thisline;
7330 args[i] = newline + diff;
7331 }
7332
7333 diff = var_end - thisline;
7334 var_end = newline + diff;
7335 diff = end - thisline;
7336 end = newline + diff;
7337 diff = line - thisline;
7338 line = newline + diff;
7339 thisline = newline;
7340 }
7341 linesize = newlinesize;
7342 }
7343
7344 /* insert value inside the line */
7345 memmove(line + val_len, var_end, end - var_end + 1);
7346 memcpy(line, value, val_len);
7347 end += val_len - (var_end - line);
7348 line += val_len;
7349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007350 else {
7351 line++;
7352 }
7353 }
William Lallemandb2f07452015-05-12 14:27:13 +02007354
William Lallemandf9873ba2015-05-05 17:37:14 +02007355 if (dquote) {
7356 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7357 err_code |= ERR_ALERT | ERR_FATAL;
7358 }
7359
7360 if (squote) {
7361 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7362 err_code |= ERR_ALERT | ERR_FATAL;
7363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007364
7365 /* empty line */
7366 if (!**args)
7367 continue;
7368
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007369 if (*line) {
7370 /* we had to stop due to too many args.
7371 * Let's terminate the string, print the offending part then cut the
7372 * last arg.
7373 */
7374 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7375 line++;
7376 *line = '\0';
7377
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007378 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007379 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007380 err_code |= ERR_ALERT | ERR_FATAL;
7381 args[arg] = line;
7382 }
7383
Willy Tarreau540abe42007-05-02 20:50:16 +02007384 /* zero out remaining args and ensure that at least one entry
7385 * is zeroed out.
7386 */
7387 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007388 args[arg] = line;
7389 }
7390
Willy Tarreau3842f002009-06-14 11:39:52 +02007391 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007392 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007393 char *tmp;
7394
Willy Tarreau3842f002009-06-14 11:39:52 +02007395 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007396 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007397 for (arg=0; *args[arg+1]; arg++)
7398 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007399 *tmp = '\0'; // fix the next arg to \0
7400 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007401 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007402 else if (!strcmp(args[0], "default")) {
7403 kwm = KWM_DEF;
7404 for (arg=0; *args[arg+1]; arg++)
7405 args[arg] = args[arg+1]; // shift args after inversion
7406 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007407
William Lallemand0f99e342011-10-12 17:50:54 +02007408 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7409 strcmp(args[0], "log") != 0) {
7410 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007411 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007412 }
7413
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007414 /* detect section start */
7415 list_for_each_entry(ics, &sections, list) {
7416 if (strcmp(args[0], ics->section_name) == 0) {
7417 cursection = ics->section_name;
7418 cs = ics;
7419 break;
7420 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007421 }
7422
William Lallemandd2ff56d2017-10-16 11:06:50 +02007423 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007424 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007425 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007426 } else {
7427 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007428
William Lallemandd2ff56d2017-10-16 11:06:50 +02007429 if (pcs != cs && pcs && pcs->post_section_parser) {
7430 err_code |= pcs->post_section_parser();
7431 if (err_code & ERR_ABORT)
7432 goto err;
7433 }
7434
7435 err_code |= cs->section_parser(file, linenum, args, kwm);
7436 if (err_code & ERR_ABORT)
7437 goto err;
7438 }
7439 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007440 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007441
7442 if (pcs == cs && pcs && pcs->post_section_parser)
7443 err_code |= pcs->post_section_parser();
7444
7445err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007446 free(cfg_scope);
7447 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007448 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007449 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007450 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007451 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007452}
7453
Willy Tarreau64ab6072014-09-16 12:17:36 +02007454/* This function propagates processes from frontend <from> to backend <to> so
7455 * that it is always guaranteed that a backend pointed to by a frontend is
7456 * bound to all of its processes. After that, if the target is a "listen"
7457 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007458 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007459 * checked first to ensure that <to> is already bound to all processes of
7460 * <from>, there is no risk of looping and we ensure to follow the shortest
7461 * path to the destination.
7462 *
7463 * It is possible to set <to> to NULL for the first call so that the function
7464 * takes care of visiting the initial frontend in <from>.
7465 *
7466 * It is important to note that the function relies on the fact that all names
7467 * have already been resolved.
7468 */
7469void propagate_processes(struct proxy *from, struct proxy *to)
7470{
7471 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007472
7473 if (to) {
7474 /* check whether we need to go down */
7475 if (from->bind_proc &&
7476 (from->bind_proc & to->bind_proc) == from->bind_proc)
7477 return;
7478
7479 if (!from->bind_proc && !to->bind_proc)
7480 return;
7481
7482 to->bind_proc = from->bind_proc ?
7483 (to->bind_proc | from->bind_proc) : 0;
7484
7485 /* now propagate down */
7486 from = to;
7487 }
7488
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007489 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007490 return;
7491
Willy Tarreauf6b70012014-12-18 14:00:43 +01007492 if (from->state == PR_STSTOPPED)
7493 return;
7494
Willy Tarreau64ab6072014-09-16 12:17:36 +02007495 /* default_backend */
7496 if (from->defbe.be)
7497 propagate_processes(from, from->defbe.be);
7498
7499 /* use_backend */
7500 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007501 if (rule->dynamic)
7502 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007503 to = rule->be.backend;
7504 propagate_processes(from, to);
7505 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007506}
7507
Willy Tarreaubb925012009-07-23 13:36:36 +02007508/*
7509 * Returns the error code, 0 if OK, or any combination of :
7510 * - ERR_ABORT: must abort ASAP
7511 * - ERR_FATAL: we can continue parsing but not start the service
7512 * - ERR_WARN: a warning has been emitted
7513 * - ERR_ALERT: an alert has been emitted
7514 * Only the two first ones can stop processing, the two others are just
7515 * indicators.
7516 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007517int check_config_validity()
7518{
7519 int cfgerr = 0;
7520 struct proxy *curproxy = NULL;
7521 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007522 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007523 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007524 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007525 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007526 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007527
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007528 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007529 /*
7530 * Now, check for the integrity of all that we have collected.
7531 */
7532
7533 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007534 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007535
Willy Tarreau193b8c62012-11-22 00:17:38 +01007536 if (!global.tune.max_http_hdr)
7537 global.tune.max_http_hdr = MAX_HTTP_HDR;
7538
7539 if (!global.tune.cookie_len)
7540 global.tune.cookie_len = CAPTURE_LEN;
7541
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007542 if (!global.tune.requri_len)
7543 global.tune.requri_len = REQURI_LEN;
7544
Emeric Brun96fd9262017-07-05 13:33:16 +02007545 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7546
Willy Tarreau193b8c62012-11-22 00:17:38 +01007547 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7548
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007549 /* Post initialisation of the users and groups lists. */
7550 err_code = userlist_postinit();
7551 if (err_code != ERR_NONE)
7552 goto out;
7553
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007554 /* first, we will invert the proxy list order */
7555 curproxy = NULL;
7556 while (proxy) {
7557 struct proxy *next;
7558
7559 next = proxy->next;
7560 proxy->next = curproxy;
7561 curproxy = proxy;
7562 if (!next)
7563 break;
7564 proxy = next;
7565 }
7566
Willy Tarreau419ead82014-09-16 13:41:21 +02007567 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007568 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007569 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007570 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007571 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007572 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007573 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007574 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007575
Willy Tarreau050536d2012-10-04 08:47:34 +02007576 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007577 /* proxy ID not set, use automatic numbering with first
7578 * spare entry starting with next_pxid.
7579 */
7580 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7581 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7582 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007583 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007584 next_pxid++;
7585
Willy Tarreau55ea7572007-06-17 19:56:27 +02007586
Willy Tarreaubaaee002006-06-26 02:48:02 +02007587 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007588 /* ensure we don't keep listeners uselessly bound */
7589 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007590 free((void *)curproxy->table.peers.name);
7591 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007592 continue;
7593 }
7594
Willy Tarreau102df612014-05-07 23:56:38 +02007595 /* Check multi-process mode compatibility for the current proxy */
7596
7597 if (curproxy->bind_proc) {
7598 /* an explicit bind-process was specified, let's check how many
7599 * processes remain.
7600 */
David Carliere6c39412015-07-02 07:00:17 +00007601 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007602
7603 curproxy->bind_proc &= nbits(global.nbproc);
7604 if (!curproxy->bind_proc && nbproc == 1) {
7605 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);
7606 curproxy->bind_proc = 1;
7607 }
7608 else if (!curproxy->bind_proc && nbproc > 1) {
7609 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);
7610 curproxy->bind_proc = 0;
7611 }
7612 }
7613
Willy Tarreau3d209582014-05-09 17:06:11 +02007614 /* check and reduce the bind-proc of each listener */
7615 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7616 unsigned long mask;
7617
Willy Tarreau45a66cc2017-11-24 11:28:00 +01007618 /* HTTP frontends with "h2" as ALPN/NPN will work in
7619 * HTTP/2 and absolutely require buffers 16kB or larger.
7620 */
7621#ifdef USE_OPENSSL
7622 if (curproxy->mode == PR_MODE_HTTP && global.tune.bufsize < 16384) {
7623#ifdef OPENSSL_NPN_NEGOTIATED
7624 /* check NPN */
7625 if (bind_conf->ssl_conf.npn_str && strcmp(bind_conf->ssl_conf.npn_str, "\002h2") == 0) {
7626 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",
7627 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
7628 cfgerr++;
7629 }
7630#endif
7631#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7632 /* check ALPN */
7633 if (bind_conf->ssl_conf.alpn_str && strcmp(bind_conf->ssl_conf.alpn_str, "\002h2") == 0) {
7634 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",
7635 curproxy->id, bind_conf->file, bind_conf->line, global.tune.bufsize);
7636 cfgerr++;
7637 }
7638#endif
7639 } /* HTTP && bufsize < 16384 */
7640#endif
7641
Willy Tarreau3d209582014-05-09 17:06:11 +02007642 if (!bind_conf->bind_proc)
7643 continue;
7644
7645 mask = nbits(global.nbproc);
7646 if (curproxy->bind_proc)
7647 mask &= curproxy->bind_proc;
7648 /* mask cannot be null here thanks to the previous checks */
7649
David Carliere6c39412015-07-02 07:00:17 +00007650 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007651 bind_conf->bind_proc &= mask;
7652
7653 if (!bind_conf->bind_proc && nbproc == 1) {
7654 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",
7655 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7656 bind_conf->bind_proc = mask & ~(mask - 1);
7657 }
7658 else if (!bind_conf->bind_proc && nbproc > 1) {
7659 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",
7660 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7661 bind_conf->bind_proc = 0;
7662 }
7663 }
7664
Willy Tarreauff01a212009-03-15 13:46:16 +01007665 switch (curproxy->mode) {
7666 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007667 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007668 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007669 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7670 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007671 cfgerr++;
7672 }
7673
7674 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007675 Warning("config : servers will be ignored for %s '%s'.\n",
7676 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007677 break;
7678
7679 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007680 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007681 break;
7682
7683 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007684 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007685 break;
7686 }
7687
Willy Tarreauf3934b82015-08-11 11:36:45 +02007688 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7689 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7690 proxy_type_str(curproxy), curproxy->id);
7691 err_code |= ERR_WARN;
7692 }
7693
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007694 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007695 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007696 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007697 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7698 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007699 cfgerr++;
7700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007701#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007702 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007703 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7704 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007705 cfgerr++;
7706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007707#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007708 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007709 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7710 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007711 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007712 }
7713 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007714 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007715 /* If no LB algo is set in a backend, and we're not in
7716 * transparent mode, dispatch mode nor proxy mode, we
7717 * want to use balance roundrobin by default.
7718 */
7719 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7720 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007721 }
7722 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007723
Willy Tarreau1620ec32011-08-06 17:05:02 +02007724 if (curproxy->options & PR_O_DISPATCH)
7725 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7726 else if (curproxy->options & PR_O_HTTP_PROXY)
7727 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7728 else if (curproxy->options & PR_O_TRANSP)
7729 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007730
Willy Tarreau1620ec32011-08-06 17:05:02 +02007731 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7732 if (curproxy->options & PR_O_DISABLE404) {
7733 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7734 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7735 err_code |= ERR_WARN;
7736 curproxy->options &= ~PR_O_DISABLE404;
7737 }
7738 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7739 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7740 "send-state", proxy_type_str(curproxy), curproxy->id);
7741 err_code |= ERR_WARN;
7742 curproxy->options &= ~PR_O2_CHK_SNDST;
7743 }
Willy Tarreauef781042010-01-27 11:53:01 +01007744 }
7745
Simon Horman98637e52014-06-20 12:30:16 +09007746 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7747 if (!global.external_check) {
7748 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7749 curproxy->id, "option external-check");
7750 cfgerr++;
7751 }
7752 if (!curproxy->check_command) {
7753 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7754 curproxy->id, "option external-check");
7755 cfgerr++;
7756 }
7757 }
7758
Simon Horman64e34162015-02-06 11:11:57 +09007759 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007760 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7761 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007762 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7763 "'email-alert myhostname', or 'email-alert to' "
7764 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007765 "to be present).\n",
7766 proxy_type_str(curproxy), curproxy->id);
7767 err_code |= ERR_WARN;
7768 free_email_alert(curproxy);
7769 }
7770 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007771 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007772 }
7773
Simon Horman98637e52014-06-20 12:30:16 +09007774 if (curproxy->check_command) {
7775 int clear = 0;
7776 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7777 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7778 "external-check command", proxy_type_str(curproxy), curproxy->id);
7779 err_code |= ERR_WARN;
7780 clear = 1;
7781 }
7782 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007783 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007784 curproxy->id, "external-check command");
7785 cfgerr++;
7786 }
7787 if (clear) {
7788 free(curproxy->check_command);
7789 curproxy->check_command = NULL;
7790 }
7791 }
7792
7793 if (curproxy->check_path) {
7794 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7795 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7796 "external-check path", proxy_type_str(curproxy), curproxy->id);
7797 err_code |= ERR_WARN;
7798 free(curproxy->check_path);
7799 curproxy->check_path = NULL;
7800 }
7801 }
7802
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007803 /* if a default backend was specified, let's find it */
7804 if (curproxy->defbe.name) {
7805 struct proxy *target;
7806
Willy Tarreauafb39922015-05-26 12:04:09 +02007807 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007808 if (!target) {
7809 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7810 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007811 cfgerr++;
7812 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007813 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7814 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007815 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007816 } else if (target->mode != curproxy->mode &&
7817 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7818
7819 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7820 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7821 curproxy->conf.file, curproxy->conf.line,
7822 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7823 target->conf.file, target->conf.line);
7824 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007825 } else {
7826 free(curproxy->defbe.name);
7827 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007828 /* Update tot_fe_maxconn for a further fullconn's computation */
7829 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007830 /* Emit a warning if this proxy also has some servers */
7831 if (curproxy->srv) {
7832 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7833 curproxy->id);
7834 err_code |= ERR_WARN;
7835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007836 }
7837 }
7838
Emeric Brun3f783572017-01-12 11:21:28 +01007839 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7840 /* Case of listen without default backend
7841 * The curproxy will be its own default backend
7842 * so we update tot_fe_maxconn for a further
7843 * fullconn's computation */
7844 curproxy->tot_fe_maxconn += curproxy->maxconn;
7845 }
7846
Willy Tarreau55ea7572007-06-17 19:56:27 +02007847 /* find the target proxy for 'use_backend' rules */
7848 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007849 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007850 struct logformat_node *node;
7851 char *pxname;
7852
7853 /* Try to parse the string as a log format expression. If the result
7854 * of the parsing is only one entry containing a simple string, then
7855 * it's a standard string corresponding to a static rule, thus the
7856 * parsing is cancelled and be.name is restored to be resolved.
7857 */
7858 pxname = rule->be.name;
7859 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007860 curproxy->conf.args.ctx = ARGC_UBK;
7861 curproxy->conf.args.file = rule->file;
7862 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007863 err = NULL;
7864 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7865 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7866 rule->file, rule->line, pxname, err);
7867 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007868 cfgerr++;
7869 continue;
7870 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007871 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7872
7873 if (!LIST_ISEMPTY(&rule->be.expr)) {
7874 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7875 rule->dynamic = 1;
7876 free(pxname);
7877 continue;
7878 }
7879 /* simple string: free the expression and fall back to static rule */
7880 free(node->arg);
7881 free(node);
7882 }
7883
7884 rule->dynamic = 0;
7885 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007886
Willy Tarreauafb39922015-05-26 12:04:09 +02007887 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007888 if (!target) {
7889 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7890 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007891 cfgerr++;
7892 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007893 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7894 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007895 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007896 } else if (target->mode != curproxy->mode &&
7897 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7898
7899 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7900 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7901 curproxy->conf.file, curproxy->conf.line,
7902 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7903 target->conf.file, target->conf.line);
7904 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007905 } else {
7906 free((void *)rule->be.name);
7907 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007908 /* For each target of switching rules, we update
7909 * their tot_fe_maxconn, except if a previous rule point
7910 * on the same backend or on the default backend */
7911 if (rule->be.backend != curproxy->defbe.be) {
7912 struct switching_rule *swrule;
7913
7914 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7915 if (rule == swrule) {
7916 target->tot_fe_maxconn += curproxy->maxconn;
7917 break;
7918 }
7919 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7920 /* there is multiple ref of this backend */
7921 break;
7922 }
7923 }
7924 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007925 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007926 }
7927
Willy Tarreau64ab6072014-09-16 12:17:36 +02007928 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007929 list_for_each_entry(srule, &curproxy->server_rules, list) {
7930 struct server *target = findserver(curproxy, srule->srv.name);
7931
7932 if (!target) {
7933 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7934 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7935 cfgerr++;
7936 continue;
7937 }
7938 free((void *)srule->srv.name);
7939 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007940 }
7941
Emeric Brunb982a3d2010-01-04 15:45:53 +01007942 /* find the target table for 'stick' rules */
7943 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7944 struct proxy *target;
7945
Emeric Brun1d33b292010-01-04 15:47:17 +01007946 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7947 if (mrule->flags & STK_IS_STORE)
7948 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7949
Emeric Brunb982a3d2010-01-04 15:45:53 +01007950 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007951 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007952 else
7953 target = curproxy;
7954
7955 if (!target) {
7956 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7957 curproxy->id, mrule->table.name);
7958 cfgerr++;
7959 }
7960 else if (target->table.size == 0) {
7961 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7962 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7963 cfgerr++;
7964 }
Willy Tarreau12785782012-04-27 21:37:17 +02007965 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7966 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007967 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7968 cfgerr++;
7969 }
7970 else {
7971 free((void *)mrule->table.name);
7972 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007973 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007974 }
7975 }
7976
7977 /* find the target table for 'store response' rules */
7978 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7979 struct proxy *target;
7980
Emeric Brun1d33b292010-01-04 15:47:17 +01007981 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7982
Emeric Brunb982a3d2010-01-04 15:45:53 +01007983 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007984 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007985 else
7986 target = curproxy;
7987
7988 if (!target) {
7989 Alert("Proxy '%s': unable to find store table '%s'.\n",
7990 curproxy->id, mrule->table.name);
7991 cfgerr++;
7992 }
7993 else if (target->table.size == 0) {
7994 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7995 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7996 cfgerr++;
7997 }
Willy Tarreau12785782012-04-27 21:37:17 +02007998 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7999 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01008000 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
8001 cfgerr++;
8002 }
8003 else {
8004 free((void *)mrule->table.name);
8005 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02008006 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01008007 }
8008 }
8009
Christopher Faulete4e830d2017-09-18 14:51:41 +02008010 /* check validity for 'tcp-request' layer 4 rules */
8011 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
8012 err = NULL;
8013 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8014 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8015 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01008016 cfgerr++;
8017 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008018 }
8019
Christopher Faulete4e830d2017-09-18 14:51:41 +02008020 /* check validity for 'tcp-request' layer 5 rules */
8021 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
8022 err = NULL;
8023 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8024 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8025 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01008026 cfgerr++;
8027 }
8028 }
8029
Christopher Faulete4e830d2017-09-18 14:51:41 +02008030 /* check validity for 'tcp-request' layer 6 rules */
8031 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8032 err = NULL;
8033 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8034 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8035 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01008036 cfgerr++;
8037 }
8038 }
8039
Christopher Faulete4e830d2017-09-18 14:51:41 +02008040 /* check validity for 'http-request' layer 7 rules */
8041 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
8042 err = NULL;
8043 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8044 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8045 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008046 cfgerr++;
8047 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008048 }
8049
Christopher Faulete4e830d2017-09-18 14:51:41 +02008050 /* check validity for 'http-response' layer 7 rules */
8051 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
8052 err = NULL;
8053 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
8054 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8055 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02008056 cfgerr++;
8057 }
Willy Tarreau09448f72014-06-25 18:12:15 +02008058 }
8059
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008060 /* move any "block" rules at the beginning of the http-request rules */
8061 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8062 /* insert block_rules into http_req_rules at the beginning */
8063 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8064 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8065 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8066 curproxy->http_req_rules.n = curproxy->block_rules.n;
8067 LIST_INIT(&curproxy->block_rules);
8068 }
8069
Emeric Brun32da3c42010-09-23 18:39:19 +02008070 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008071 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008072
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008073 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008074 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8075 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008076 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008077 break;
8078 }
8079 }
8080
8081 if (!curpeers) {
8082 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8083 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008084 free((void *)curproxy->table.peers.name);
8085 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008086 cfgerr++;
8087 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008088 else if (curpeers->state == PR_STSTOPPED) {
8089 /* silently disable this peers section */
8090 curproxy->table.peers.p = NULL;
8091 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008092 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008093 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8094 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008095 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008096 cfgerr++;
8097 }
8098 }
8099
Simon Horman9dc49962015-01-30 11:22:59 +09008100
8101 if (curproxy->email_alert.mailers.name) {
8102 struct mailers *curmailers = mailers;
8103
8104 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02008105 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09008106 break;
Simon Horman9dc49962015-01-30 11:22:59 +09008107 }
Simon Horman9dc49962015-01-30 11:22:59 +09008108 if (!curmailers) {
8109 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8110 curproxy->id, curproxy->email_alert.mailers.name);
8111 free_email_alert(curproxy);
8112 cfgerr++;
8113 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02008114 else {
8115 err = NULL;
8116 if (init_email_alert(curmailers, curproxy, &err)) {
8117 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8118 free(err);
8119 cfgerr++;
8120 }
8121 }
Simon Horman9dc49962015-01-30 11:22:59 +09008122 }
8123
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008124 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008125 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008126 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8127 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8128 "proxy", curproxy->id);
8129 cfgerr++;
8130 goto out_uri_auth_compat;
8131 }
8132
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008133 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008134 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008135 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008136 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008137
Willy Tarreau95fa4692010-02-01 13:05:50 +01008138 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8139 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008140
8141 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008142 uri_auth_compat_req[i++] = "realm";
8143 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8144 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008145
Willy Tarreau95fa4692010-02-01 13:05:50 +01008146 uri_auth_compat_req[i++] = "unless";
8147 uri_auth_compat_req[i++] = "{";
8148 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8149 uri_auth_compat_req[i++] = "}";
8150 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008151
Willy Tarreauff011f22011-01-06 17:51:27 +01008152 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8153 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008154 cfgerr++;
8155 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008156 }
8157
Willy Tarreauff011f22011-01-06 17:51:27 +01008158 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008159
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008160 if (curproxy->uri_auth->auth_realm) {
8161 free(curproxy->uri_auth->auth_realm);
8162 curproxy->uri_auth->auth_realm = NULL;
8163 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008164
8165 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008166 }
8167out_uri_auth_compat:
8168
Dragan Dosen43885c72015-10-01 13:18:13 +02008169 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008170 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008171 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8172 if (!curproxy->conf.logformat_sd_string) {
8173 /* set the default logformat_sd_string */
8174 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8175 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008176 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008177 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008178 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008179
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008180 /* compile the log format */
8181 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008182 if (curproxy->conf.logformat_string != default_http_log_format &&
8183 curproxy->conf.logformat_string != default_tcp_log_format &&
8184 curproxy->conf.logformat_string != clf_http_log_format)
8185 free(curproxy->conf.logformat_string);
8186 curproxy->conf.logformat_string = NULL;
8187 free(curproxy->conf.lfs_file);
8188 curproxy->conf.lfs_file = NULL;
8189 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008190
8191 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8192 free(curproxy->conf.logformat_sd_string);
8193 curproxy->conf.logformat_sd_string = NULL;
8194 free(curproxy->conf.lfsd_file);
8195 curproxy->conf.lfsd_file = NULL;
8196 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008197 }
8198
Willy Tarreau62a61232013-04-12 18:13:46 +02008199 if (curproxy->conf.logformat_string) {
8200 curproxy->conf.args.ctx = ARGC_LOG;
8201 curproxy->conf.args.file = curproxy->conf.lfs_file;
8202 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008203 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008204 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008205 SMP_VAL_FE_LOG_END, &err)) {
8206 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8207 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8208 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008209 cfgerr++;
8210 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008211 curproxy->conf.args.file = NULL;
8212 curproxy->conf.args.line = 0;
8213 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008214
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008215 if (curproxy->conf.logformat_sd_string) {
8216 curproxy->conf.args.ctx = ARGC_LOGSD;
8217 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8218 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008219 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008220 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 +01008221 SMP_VAL_FE_LOG_END, &err)) {
8222 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8223 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8224 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008225 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008226 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8227 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8228 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8229 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008230 cfgerr++;
8231 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008232 curproxy->conf.args.file = NULL;
8233 curproxy->conf.args.line = 0;
8234 }
8235
Willy Tarreau62a61232013-04-12 18:13:46 +02008236 if (curproxy->conf.uniqueid_format_string) {
8237 curproxy->conf.args.ctx = ARGC_UIF;
8238 curproxy->conf.args.file = curproxy->conf.uif_file;
8239 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008240 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008241 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 +01008242 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8243 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8244 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8245 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008246 cfgerr++;
8247 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008248 curproxy->conf.args.file = NULL;
8249 curproxy->conf.args.line = 0;
8250 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008251
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008252 /* only now we can check if some args remain unresolved.
8253 * This must be done after the users and groups resolution.
8254 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008255 cfgerr += smp_resolve_args(curproxy);
8256 if (!cfgerr)
8257 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008258
Willy Tarreau2738a142006-07-08 17:28:09 +02008259 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008260 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008261 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008262 (!curproxy->timeout.connect ||
8263 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008264 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008265 " | While not properly invalid, you will certainly encounter various problems\n"
8266 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008267 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008268 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008269 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008270 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008271
Willy Tarreau1fa31262007-12-03 00:36:16 +01008272 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8273 * We must still support older configurations, so let's find out whether those
8274 * parameters have been set or must be copied from contimeouts.
8275 */
8276 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008277 if (!curproxy->timeout.tarpit ||
8278 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008279 /* tarpit timeout not set. We search in the following order:
8280 * default.tarpit, curr.connect, default.connect.
8281 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008282 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008283 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008284 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008285 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008286 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008287 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008288 }
8289 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008290 (!curproxy->timeout.queue ||
8291 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008292 /* queue timeout not set. We search in the following order:
8293 * default.queue, curr.connect, default.connect.
8294 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008295 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008296 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008297 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008298 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008299 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008300 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008301 }
8302 }
8303
Willy Tarreau1620ec32011-08-06 17:05:02 +02008304 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008305 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008306 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008307 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008308 }
8309
Willy Tarreau215663d2014-06-13 18:30:23 +02008310 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8311 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8312 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8313 proxy_type_str(curproxy), curproxy->id);
8314 err_code |= ERR_WARN;
8315 }
8316
Willy Tarreau193b8c62012-11-22 00:17:38 +01008317 /* ensure that cookie capture length is not too large */
8318 if (curproxy->capture_len >= global.tune.cookie_len) {
8319 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8320 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8321 err_code |= ERR_WARN;
8322 curproxy->capture_len = global.tune.cookie_len - 1;
8323 }
8324
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008325 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008326 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008327 curproxy->req_cap_pool = create_pool("ptrcap",
8328 curproxy->nb_req_cap * sizeof(char *),
8329 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008330 }
8331
8332 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008333 curproxy->rsp_cap_pool = create_pool("ptrcap",
8334 curproxy->nb_rsp_cap * sizeof(char *),
8335 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008336 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008337
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008338 switch (curproxy->load_server_state_from_file) {
8339 case PR_SRV_STATE_FILE_UNSPEC:
8340 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8341 break;
8342 case PR_SRV_STATE_FILE_GLOBAL:
8343 if (!global.server_state_file) {
8344 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",
8345 curproxy->id);
8346 err_code |= ERR_WARN;
8347 }
8348 break;
8349 }
8350
Willy Tarreaubaaee002006-06-26 02:48:02 +02008351 /* first, we will invert the servers list order */
8352 newsrv = NULL;
8353 while (curproxy->srv) {
8354 struct server *next;
8355
8356 next = curproxy->srv->next;
8357 curproxy->srv->next = newsrv;
8358 newsrv = curproxy->srv;
8359 if (!next)
8360 break;
8361 curproxy->srv = next;
8362 }
8363
Willy Tarreau17edc812014-01-03 12:14:34 +01008364 /* Check that no server name conflicts. This causes trouble in the stats.
8365 * We only emit a warning for the first conflict affecting each server,
8366 * in order to avoid combinatory explosion if all servers have the same
8367 * name. We do that only for servers which do not have an explicit ID,
8368 * because these IDs were made also for distinguishing them and we don't
8369 * want to annoy people who correctly manage them.
8370 */
8371 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8372 struct server *other_srv;
8373
8374 if (newsrv->puid)
8375 continue;
8376
8377 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8378 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8379 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8380 newsrv->conf.file, newsrv->conf.line,
8381 proxy_type_str(curproxy), curproxy->id,
8382 newsrv->id, other_srv->conf.line);
8383 break;
8384 }
8385 }
8386 }
8387
Willy Tarreaudd701652010-05-25 23:03:02 +02008388 /* assign automatic UIDs to servers which don't have one yet */
8389 next_id = 1;
8390 newsrv = curproxy->srv;
8391 while (newsrv != NULL) {
8392 if (!newsrv->puid) {
8393 /* server ID not set, use automatic numbering with first
8394 * spare entry starting with next_svid.
8395 */
8396 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8397 newsrv->conf.id.key = newsrv->puid = next_id;
8398 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8399 }
8400 next_id++;
8401 newsrv = newsrv->next;
8402 }
8403
Willy Tarreau20697042007-11-15 23:26:18 +01008404 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008405 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008406
Willy Tarreau62c3be22012-01-20 13:12:32 +01008407 /*
8408 * If this server supports a maxconn parameter, it needs a dedicated
8409 * tasks to fill the emptied slots when a connection leaves.
8410 * Also, resolve deferred tracking dependency if needed.
8411 */
8412 newsrv = curproxy->srv;
8413 while (newsrv != NULL) {
8414 if (newsrv->minconn > newsrv->maxconn) {
8415 /* Only 'minconn' was specified, or it was higher than or equal
8416 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8417 * this will avoid further useless expensive computations.
8418 */
8419 newsrv->maxconn = newsrv->minconn;
8420 } else if (newsrv->maxconn && !newsrv->minconn) {
8421 /* minconn was not specified, so we set it to maxconn */
8422 newsrv->minconn = newsrv->maxconn;
8423 }
8424
Willy Tarreau17d45382016-12-22 21:16:08 +01008425 /* this will also properly set the transport layer for prod and checks */
8426 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8427 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8428 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8429 }
Emeric Brun94324a42012-10-11 14:00:19 +02008430
Willy Tarreau2f075e92013-12-03 11:11:34 +01008431 /* set the check type on the server */
8432 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8433
Willy Tarreau62c3be22012-01-20 13:12:32 +01008434 if (newsrv->trackit) {
8435 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008436 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008437 char *pname, *sname;
8438
8439 pname = newsrv->trackit;
8440 sname = strrchr(pname, '/');
8441
8442 if (sname)
8443 *sname++ = '\0';
8444 else {
8445 sname = pname;
8446 pname = NULL;
8447 }
8448
8449 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008450 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008451 if (!px) {
8452 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8453 proxy_type_str(curproxy), curproxy->id,
8454 newsrv->id, pname);
8455 cfgerr++;
8456 goto next_srv;
8457 }
8458 } else
8459 px = curproxy;
8460
8461 srv = findserver(px, sname);
8462 if (!srv) {
8463 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8464 proxy_type_str(curproxy), curproxy->id,
8465 newsrv->id, sname);
8466 cfgerr++;
8467 goto next_srv;
8468 }
8469
Willy Tarreau32091232014-05-16 13:52:00 +02008470 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8471 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8472 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008473 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008474 "tracking as it does not have any check nor agent enabled.\n",
8475 proxy_type_str(curproxy), curproxy->id,
8476 newsrv->id, px->id, srv->id);
8477 cfgerr++;
8478 goto next_srv;
8479 }
8480
8481 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8482
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008483 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008484 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8485 "belongs to a tracking chain looping back to %s/%s.\n",
8486 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008487 newsrv->id, px->id, srv->id, px->id,
8488 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008489 cfgerr++;
8490 goto next_srv;
8491 }
8492
8493 if (curproxy != px &&
8494 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8495 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8496 "tracking: disable-on-404 option inconsistency.\n",
8497 proxy_type_str(curproxy), curproxy->id,
8498 newsrv->id, px->id, srv->id);
8499 cfgerr++;
8500 goto next_srv;
8501 }
8502
Willy Tarreau62c3be22012-01-20 13:12:32 +01008503 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008504 newsrv->tracknext = srv->trackers;
8505 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008506
8507 free(newsrv->trackit);
8508 newsrv->trackit = NULL;
8509 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008510
Willy Tarreau62c3be22012-01-20 13:12:32 +01008511 next_srv:
8512 newsrv = newsrv->next;
8513 }
8514
Olivier Houchard4e694042017-03-14 20:01:29 +01008515 /*
8516 * Try to generate dynamic cookies for servers now.
8517 * It couldn't be done earlier, since at the time we parsed
8518 * the server line, we may not have known yet that we
8519 * should use dynamic cookies, or the secret key may not
8520 * have been provided yet.
8521 */
8522 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8523 newsrv = curproxy->srv;
8524 while (newsrv != NULL) {
8525 srv_set_dyncookie(newsrv);
8526 newsrv = newsrv->next;
8527 }
8528
8529 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008530 /* We have to initialize the server lookup mechanism depending
8531 * on what LB algorithm was choosen.
8532 */
8533
8534 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8535 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8536 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008537 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8538 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8539 init_server_map(curproxy);
8540 } else {
8541 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8542 fwrr_init_server_groups(curproxy);
8543 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008544 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008545
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008546 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008547 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8548 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8549 fwlc_init_server_tree(curproxy);
8550 } else {
8551 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8552 fas_init_server_tree(curproxy);
8553 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008554 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008555
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008556 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008557 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8558 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8559 chash_init_server_tree(curproxy);
8560 } else {
8561 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8562 init_server_map(curproxy);
8563 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008564 break;
8565 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008566 HA_SPIN_INIT(&curproxy->lbprm.lock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02008567
8568 if (curproxy->options & PR_O_LOGASAP)
8569 curproxy->to_log &= ~LW_BYTES;
8570
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008571 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008572 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8573 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008574 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8575 proxy_type_str(curproxy), curproxy->id);
8576 err_code |= ERR_WARN;
8577 }
8578
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008579 if (curproxy->mode != PR_MODE_HTTP) {
8580 int optnum;
8581
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008582 if (curproxy->uri_auth) {
8583 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8584 proxy_type_str(curproxy), curproxy->id);
8585 err_code |= ERR_WARN;
8586 curproxy->uri_auth = NULL;
8587 }
8588
Willy Tarreaude7dc882017-03-10 11:49:21 +01008589 if (curproxy->capture_name) {
8590 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8591 proxy_type_str(curproxy), curproxy->id);
8592 err_code |= ERR_WARN;
8593 }
8594
8595 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8596 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8597 proxy_type_str(curproxy), curproxy->id);
8598 err_code |= ERR_WARN;
8599 }
8600
8601 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8602 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8603 proxy_type_str(curproxy), curproxy->id);
8604 err_code |= ERR_WARN;
8605 }
8606
8607 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8608 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8609 proxy_type_str(curproxy), curproxy->id);
8610 err_code |= ERR_WARN;
8611 }
8612
8613 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8614 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8615 proxy_type_str(curproxy), curproxy->id);
8616 err_code |= ERR_WARN;
8617 }
8618
Willy Tarreau87cf5142011-08-19 22:57:24 +02008619 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008620 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8621 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8622 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008623 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008624 }
8625
8626 if (curproxy->options & PR_O_ORGTO) {
8627 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8628 "originalto", proxy_type_str(curproxy), curproxy->id);
8629 err_code |= ERR_WARN;
8630 curproxy->options &= ~PR_O_ORGTO;
8631 }
8632
8633 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8634 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8635 (curproxy->cap & cfg_opts[optnum].cap) &&
8636 (curproxy->options & cfg_opts[optnum].val)) {
8637 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8638 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8639 err_code |= ERR_WARN;
8640 curproxy->options &= ~cfg_opts[optnum].val;
8641 }
8642 }
8643
8644 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8645 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8646 (curproxy->cap & cfg_opts2[optnum].cap) &&
8647 (curproxy->options2 & cfg_opts2[optnum].val)) {
8648 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8649 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8650 err_code |= ERR_WARN;
8651 curproxy->options2 &= ~cfg_opts2[optnum].val;
8652 }
8653 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008654
Willy Tarreau29fbe512015-08-20 19:35:14 +02008655#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008656 if (curproxy->conn_src.bind_hdr_occ) {
8657 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008658 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008659 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008660 err_code |= ERR_WARN;
8661 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008662#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008663 }
8664
Willy Tarreaubaaee002006-06-26 02:48:02 +02008665 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008666 * ensure that we're not cross-dressing a TCP server into HTTP.
8667 */
8668 newsrv = curproxy->srv;
8669 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008670 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008671 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8672 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008673 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008674 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008675
Willy Tarreau0cec3312011-10-31 13:49:26 +01008676 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8677 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8678 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8679 err_code |= ERR_WARN;
8680 }
8681
Willy Tarreauc93cd162014-05-13 15:54:22 +02008682 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008683 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8684 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8685 err_code |= ERR_WARN;
8686 }
8687
Willy Tarreau29fbe512015-08-20 19:35:14 +02008688#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008689 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8690 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008691 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 +01008692 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008693 err_code |= ERR_WARN;
8694 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008695#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008696
8697 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8698 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8699 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8700 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8701 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8702 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",
8703 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8704 err_code |= ERR_WARN;
8705 }
8706
8707
8708 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8709 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",
8710 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8711 err_code |= ERR_WARN;
8712 }
8713 }
8714
Willy Tarreau21d2af32008-02-14 20:25:24 +01008715 newsrv = newsrv->next;
8716 }
8717
Willy Tarreaue42bd962014-09-16 16:21:19 +02008718 /* check if we have a frontend with "tcp-request content" looking at L7
8719 * with no inspect-delay
8720 */
8721 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008722 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8723 if (arule->action == ACT_TCP_CAPTURE &&
8724 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008725 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008726 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8727 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008728 break;
8729 }
8730
Christopher Faulete4e830d2017-09-18 14:51:41 +02008731 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008732 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8733 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8734 " This means that these rules will randomly find their contents. This can be fixed by"
8735 " setting the tcp-request inspect-delay.\n",
8736 proxy_type_str(curproxy), curproxy->id);
8737 err_code |= ERR_WARN;
8738 }
8739 }
8740
Christopher Fauletd7c91962015-04-30 11:48:27 +02008741 /* Check filter configuration, if any */
8742 cfgerr += flt_check(curproxy);
8743
Willy Tarreauc1a21672009-08-16 22:37:44 +02008744 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008745 if (!curproxy->accept)
8746 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008747
Willy Tarreauc1a21672009-08-16 22:37:44 +02008748 if (curproxy->tcp_req.inspect_delay ||
8749 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008750 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008751
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008752 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008753 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008754 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008755 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008756
8757 /* both TCP and HTTP must check switching rules */
8758 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008759
8760 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008761 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008762 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8763 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 +01008764 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008765 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8766 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008767 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008768 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008769 }
8770
8771 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008772 if (curproxy->tcp_req.inspect_delay ||
8773 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8774 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8775
Emeric Brun97679e72010-09-23 17:56:44 +02008776 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8777 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8778
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008779 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008780 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008781 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008782 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008783
8784 /* If the backend does requires RDP cookie persistence, we have to
8785 * enable the corresponding analyser.
8786 */
8787 if (curproxy->options2 & PR_O2_RDPC_PRST)
8788 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008789
8790 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008791 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008792 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8793 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 +01008794 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008795 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8796 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008797 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008798 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008799 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008800 }
8801
8802 /***********************************************************/
8803 /* At this point, target names have already been resolved. */
8804 /***********************************************************/
8805
8806 /* Check multi-process mode compatibility */
8807
8808 if (global.nbproc > 1 && global.stats_fe) {
8809 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8810 unsigned long mask;
8811
8812 mask = nbits(global.nbproc);
8813 if (global.stats_fe->bind_proc)
8814 mask &= global.stats_fe->bind_proc;
8815
8816 if (bind_conf->bind_proc)
8817 mask &= bind_conf->bind_proc;
8818
8819 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008820 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008821 break;
8822 }
8823 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8824 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");
8825 }
8826 }
8827
8828 /* Make each frontend inherit bind-process from its listeners when not specified. */
8829 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8830 if (curproxy->bind_proc)
8831 continue;
8832
8833 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8834 unsigned long mask;
8835
Willy Tarreaue428b082015-05-04 21:57:58 +02008836 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008837 curproxy->bind_proc |= mask;
8838 }
8839
8840 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008841 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008842 }
8843
8844 if (global.stats_fe) {
8845 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8846 unsigned long mask;
8847
Cyril Bonté06181952016-02-24 00:14:54 +01008848 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008849 global.stats_fe->bind_proc |= mask;
8850 }
8851 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008852 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008853 }
8854
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008855 /* propagate bindings from frontends to backends. Don't do it if there
8856 * are any fatal errors as we must not call it with unresolved proxies.
8857 */
8858 if (!cfgerr) {
8859 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8860 if (curproxy->cap & PR_CAP_FE)
8861 propagate_processes(curproxy, NULL);
8862 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008863 }
8864
8865 /* Bind each unbound backend to all processes when not specified. */
8866 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8867 if (curproxy->bind_proc)
8868 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008869 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008870 }
8871
8872 /*******************************************************/
8873 /* At this step, all proxies have a non-null bind_proc */
8874 /*******************************************************/
8875
8876 /* perform the final checks before creating tasks */
8877
8878 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8879 struct listener *listener;
8880 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008881
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008882 /* Configure SSL for each bind line.
8883 * Note: if configuration fails at some point, the ->ctx member
8884 * remains NULL so that listeners can later detach.
8885 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008886 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008887 if (bind_conf->xprt->prepare_bind_conf &&
8888 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008889 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008890 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008891
Willy Tarreaue6b98942007-10-29 01:09:36 +01008892 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008893 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008894 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008895 int nbproc;
8896
8897 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008898 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008899 nbits(global.nbproc));
8900
8901 if (!nbproc) /* no intersection between listener and frontend */
8902 nbproc = 1;
8903
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008904 if (!listener->luid) {
8905 /* listener ID not set, use automatic numbering with first
8906 * spare entry starting with next_luid.
8907 */
8908 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8909 listener->conf.id.key = listener->luid = next_id;
8910 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008911 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008912 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008913
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008914 /* enable separate counters */
8915 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008916 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008917 if (!listener->name)
8918 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008919 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008920
Willy Tarreaue6b98942007-10-29 01:09:36 +01008921 if (curproxy->options & PR_O_TCP_NOLING)
8922 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008923 if (!listener->maxconn)
8924 listener->maxconn = curproxy->maxconn;
8925 if (!listener->backlog)
8926 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008927 if (!listener->maxaccept)
8928 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8929
8930 /* we want to have an optimal behaviour on single process mode to
8931 * maximize the work at once, but in multi-process we want to keep
8932 * some fairness between processes, so we target half of the max
8933 * number of events to be balanced over all the processes the proxy
8934 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8935 * used to disable the limit.
8936 */
8937 if (listener->maxaccept > 0) {
8938 if (nbproc > 1)
8939 listener->maxaccept = (listener->maxaccept + 1) / 2;
8940 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8941 }
8942
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008943 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008944 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008945 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008946
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008947 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008948 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008949
Willy Tarreau620408f2016-10-21 16:37:51 +02008950 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8951 listener->options |= LI_O_TCP_L5_RULES;
8952
Willy Tarreaude3041d2010-05-31 10:56:17 +02008953 if (curproxy->mon_mask.s_addr)
8954 listener->options |= LI_O_CHK_MONNET;
8955
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008956 /* smart accept mode is automatic in HTTP mode */
8957 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008958 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008959 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8960 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008961 }
8962
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008963 /* Release unused SSL configs */
8964 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008965 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8966 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008967 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008968
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008969 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008970 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008971 int count, maxproc = 0;
8972
8973 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008974 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008975 if (count > maxproc)
8976 maxproc = count;
8977 }
8978 /* backends have 0, frontends have 1 or more */
8979 if (maxproc != 1)
8980 Warning("Proxy '%s': in multi-process mode, stats will be"
8981 " limited to process assigned to the current request.\n",
8982 curproxy->id);
8983
Willy Tarreau102df612014-05-07 23:56:38 +02008984 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8985 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8986 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008987 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008988 }
Willy Tarreau102df612014-05-07 23:56:38 +02008989 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8990 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8991 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008992 }
8993 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008994
8995 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02008996 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02008997 if (curproxy->task) {
8998 curproxy->task->context = curproxy;
8999 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009000 } else {
9001 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9002 curproxy->id);
9003 cfgerr++;
9004 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009005 }
9006
Willy Tarreaufbb78422011-06-05 15:38:35 +02009007 /* automatically compute fullconn if not set. We must not do it in the
9008 * loop above because cross-references are not yet fully resolved.
9009 */
9010 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9011 /* If <fullconn> is not set, let's set it to 10% of the sum of
9012 * the possible incoming frontend's maxconns.
9013 */
9014 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009015 /* we have the sum of the maxconns in <total>. We only
9016 * keep 10% of that sum to set the default fullconn, with
9017 * a hard minimum of 1 (to avoid a divide by zero).
9018 */
Emeric Brun3f783572017-01-12 11:21:28 +01009019 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009020 if (!curproxy->fullconn)
9021 curproxy->fullconn = 1;
9022 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009023 }
9024
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009025 /*
9026 * Recount currently required checks.
9027 */
9028
9029 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9030 int optnum;
9031
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009032 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9033 if (curproxy->options & cfg_opts[optnum].val)
9034 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009035
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009036 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9037 if (curproxy->options2 & cfg_opts2[optnum].val)
9038 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009039 }
9040
Willy Tarreau0fca4832015-05-01 19:12:05 +02009041 /* compute the required process bindings for the peers */
9042 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9043 if (curproxy->table.peers.p)
9044 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9045
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009046 if (cfg_peers) {
9047 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009048 struct peer *p, *pb;
9049
Willy Tarreau1e273012015-05-01 19:15:17 +02009050 /* Remove all peers sections which don't have a valid listener,
9051 * which are not used by any table, or which are bound to more
9052 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009053 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009054 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009055 while (*last) {
9056 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009057
9058 if (curpeers->state == PR_STSTOPPED) {
9059 /* the "disabled" keyword was present */
9060 if (curpeers->peers_fe)
9061 stop_proxy(curpeers->peers_fe);
9062 curpeers->peers_fe = NULL;
9063 }
9064 else if (!curpeers->peers_fe) {
9065 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9066 curpeers->id, localpeer);
9067 }
David Carliere6c39412015-07-02 07:00:17 +00009068 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009069 /* either it's totally stopped or too much used */
9070 if (curpeers->peers_fe->bind_proc) {
9071 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009072 "running in different processes (%d different ones). "
9073 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009074 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009075 cfgerr++;
9076 }
9077 stop_proxy(curpeers->peers_fe);
9078 curpeers->peers_fe = NULL;
9079 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009080 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009081 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009082 last = &curpeers->next;
9083 continue;
9084 }
9085
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009086 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009087 p = curpeers->remote;
9088 while (p) {
9089 pb = p->next;
9090 free(p->id);
9091 free(p);
9092 p = pb;
9093 }
9094
9095 /* Destroy and unlink this curpeers section.
9096 * Note: curpeers is backed up into *last.
9097 */
9098 free(curpeers->id);
9099 curpeers = curpeers->next;
9100 free(*last);
9101 *last = curpeers;
9102 }
9103 }
9104
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009105 /* initialize stick-tables on backend capable proxies. This must not
9106 * be done earlier because the data size may be discovered while parsing
9107 * other proxies.
9108 */
9109 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9110 if (curproxy->state == PR_STSTOPPED)
9111 continue;
9112
9113 if (!stktable_init(&curproxy->table)) {
9114 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9115 cfgerr++;
9116 }
9117 }
9118
Simon Horman0d16a402015-01-30 11:22:58 +09009119 if (mailers) {
9120 struct mailers *curmailers = mailers, **last;
9121 struct mailer *m, *mb;
9122
9123 /* Remove all mailers sections which don't have a valid listener.
9124 * This can happen when a mailers section is never referenced.
9125 */
9126 last = &mailers;
9127 while (*last) {
9128 curmailers = *last;
9129 if (curmailers->users) {
9130 last = &curmailers->next;
9131 continue;
9132 }
9133
9134 Warning("Removing incomplete section 'mailers %s'.\n",
9135 curmailers->id);
9136
9137 m = curmailers->mailer_list;
9138 while (m) {
9139 mb = m->next;
9140 free(m->id);
9141 free(m);
9142 m = mb;
9143 }
9144
9145 /* Destroy and unlink this curmailers section.
9146 * Note: curmailers is backed up into *last.
9147 */
9148 free(curmailers->id);
9149 curmailers = curmailers->next;
9150 free(*last);
9151 *last = curmailers;
9152 }
9153 }
9154
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009155 /* Update server_state_file_name to backend name if backend is supposed to use
9156 * a server-state file locally defined and none has been provided */
9157 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9158 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9159 curproxy->server_state_file_name == NULL)
9160 curproxy->server_state_file_name = strdup(curproxy->id);
9161 }
9162
Willy Tarreau34eb6712011-10-24 18:15:04 +02009163 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009164 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009165 MEM_F_SHARED);
9166
William Lallemand48b4bb42017-10-23 14:36:34 +02009167 list_for_each_entry(postparser, &postparsers, list) {
9168 if (postparser->func)
9169 cfgerr += postparser->func();
9170 }
9171
Willy Tarreaubb925012009-07-23 13:36:36 +02009172 if (cfgerr > 0)
9173 err_code |= ERR_ALERT | ERR_FATAL;
9174 out:
9175 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009176}
9177
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009178/*
9179 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9180 * parsing sessions.
9181 */
9182void cfg_register_keywords(struct cfg_kw_list *kwl)
9183{
9184 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9185}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009186
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009187/*
9188 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9189 */
9190void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9191{
9192 LIST_DEL(&kwl->list);
9193 LIST_INIT(&kwl->list);
9194}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009195
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009196/* this function register new section in the haproxy configuration file.
9197 * <section_name> is the name of this new section and <section_parser>
9198 * is the called parser. If two section declaration have the same name,
9199 * only the first declared is used.
9200 */
9201int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009202 int (*section_parser)(const char *, int, char **, int),
9203 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009204{
9205 struct cfg_section *cs;
9206
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009207 list_for_each_entry(cs, &sections, list) {
9208 if (strcmp(cs->section_name, section_name) == 0) {
9209 Alert("register section '%s': already registered.\n", section_name);
9210 return 0;
9211 }
9212 }
9213
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009214 cs = calloc(1, sizeof(*cs));
9215 if (!cs) {
9216 Alert("register section '%s': out of memory.\n", section_name);
9217 return 0;
9218 }
9219
9220 cs->section_name = section_name;
9221 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009222 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009223
9224 LIST_ADDQ(&sections, &cs->list);
9225
9226 return 1;
9227}
9228
William Lallemand48b4bb42017-10-23 14:36:34 +02009229/* this function register a new function which will be called once the haproxy
9230 * configuration file has been parsed. It's useful to check dependencies
9231 * between sections or to resolve items once everything is parsed.
9232 */
9233int cfg_register_postparser(char *name, int (*func)())
9234{
9235 struct cfg_postparser *cp;
9236
9237 cp = calloc(1, sizeof(*cp));
9238 if (!cp) {
9239 Alert("register postparser '%s': out of memory.\n", name);
9240 return 0;
9241 }
9242 cp->name = name;
9243 cp->func = func;
9244
9245 LIST_ADDQ(&postparsers, &cp->list);
9246
9247 return 1;
9248}
9249
Willy Tarreaubaaee002006-06-26 02:48:02 +02009250/*
David Carlier845efb52015-09-25 11:49:18 +01009251 * free all config section entries
9252 */
9253void cfg_unregister_sections(void)
9254{
9255 struct cfg_section *cs, *ics;
9256
9257 list_for_each_entry_safe(cs, ics, &sections, list) {
9258 LIST_DEL(&cs->list);
9259 free(cs);
9260 }
9261}
9262
Christopher Faulet7110b402016-10-26 11:09:44 +02009263void cfg_backup_sections(struct list *backup_sections)
9264{
9265 struct cfg_section *cs, *ics;
9266
9267 list_for_each_entry_safe(cs, ics, &sections, list) {
9268 LIST_DEL(&cs->list);
9269 LIST_ADDQ(backup_sections, &cs->list);
9270 }
9271}
9272
9273void cfg_restore_sections(struct list *backup_sections)
9274{
9275 struct cfg_section *cs, *ics;
9276
9277 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9278 LIST_DEL(&cs->list);
9279 LIST_ADDQ(&sections, &cs->list);
9280 }
9281}
9282
Willy Tarreau659fbf02016-05-26 17:55:28 +02009283__attribute__((constructor))
9284static void cfgparse_init(void)
9285{
9286 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009287 cfg_register_section("listen", cfg_parse_listen, NULL);
9288 cfg_register_section("frontend", cfg_parse_listen, NULL);
9289 cfg_register_section("backend", cfg_parse_listen, NULL);
9290 cfg_register_section("defaults", cfg_parse_listen, NULL);
9291 cfg_register_section("global", cfg_parse_global, NULL);
9292 cfg_register_section("userlist", cfg_parse_users, NULL);
9293 cfg_register_section("peers", cfg_parse_peers, NULL);
9294 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9295 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9296 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009297}
9298
David Carlier845efb52015-09-25 11:49:18 +01009299/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009300 * Local variables:
9301 * c-indent-level: 8
9302 * c-basic-offset: 8
9303 * End:
9304 */