blob: 7b5572f79e510a712a12ce2fc19f7d0f1135bf85 [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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
William Lallemand9ed62032016-11-21 17:49:11 +010062#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020063#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020064#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020065#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020066#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010067#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020068#include <proto/lb_fwlc.h>
69#include <proto/lb_fwrr.h>
70#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020071#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010074#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020075#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020083#include <proto/raw_sock.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
Emeric Brunfc0421f2012-09-07 17:30:07 +020088#ifdef USE_OPENSSL
89#include <types/ssl_sock.h>
90#include <proto/ssl_sock.h>
91#include <proto/shctx.h>
92#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020093
Willy Tarreauf3c69202006-07-09 16:42:34 +020094/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
95 * ssl-hello-chk option to ensure that the remote server speaks SSL.
96 *
97 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
98 */
99const char sslv3_client_hello_pkt[] = {
100 "\x16" /* ContentType : 0x16 = Hanshake */
101 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
102 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
103 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
104 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
105 "\x03\x00" /* Hello Version : 0x0300 = v3 */
106 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
107 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
108 "\x00" /* Session ID length : empty (no session ID) */
109 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
110 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
111 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
112 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
113 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
114 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
115 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
116 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
117 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
118 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
119 "\x00\x38" "\x00\x39" "\x00\x3A"
120 "\x01" /* Compression Length : 0x01 = 1 byte for types */
121 "\x00" /* Compression Type : 0x00 = NULL compression */
122};
123
Willy Tarreau3842f002009-06-14 11:39:52 +0200124/* various keyword modifiers */
125enum kw_mod {
126 KWM_STD = 0, /* normal */
127 KWM_NO, /* "no" prefixed before the keyword */
128 KWM_DEF, /* "default" prefixed before the keyword */
129};
130
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100131/* permit to store configuration section */
132struct cfg_section {
133 struct list list;
134 char *section_name;
135 int (*section_parser)(const char *, int, char **, int);
136};
137
138/* Used to chain configuration sections definitions. This list
139 * stores struct cfg_section
140 */
141struct list sections = LIST_HEAD_INIT(sections);
142
Willy Tarreau13943ab2006-12-31 00:24:10 +0100143/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100145 const char *name;
146 unsigned int val;
147 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100148 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150};
151
152/* proxy->options */
153static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100154{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
156 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
157 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
158 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
159 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
160 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200162 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200163 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100164 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
166 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
167 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100169#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100171#else
172 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100173#endif
174
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100175 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100176};
177
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100178/* proxy->options2 */
179static const struct cfg_opt cfg_opts2[] =
180{
181#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
183 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
184 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100185#else
186 { "splice-request", 0, 0, 0, 0 },
187 { "splice-response", 0, 0, 0, 0 },
188 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100189#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100190 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
191 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
192 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
193 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
194 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
195 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
196 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
197 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
198 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400199 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100200 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200201 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200202 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100203 { NULL, 0, 0, 0 }
204};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau6daf3432008-01-22 16:44:08 +0100206static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
208int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100209int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100210char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200212/* List head of all known configuration keywords */
213static struct cfg_kw_list cfg_keywords = {
214 .list = LIST_HEAD_INIT(cfg_keywords.list)
215};
216
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217/*
218 * converts <str> to a list of listeners which are dynamically allocated.
219 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
220 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
221 * - <port> is a numerical port from 1 to 65535 ;
222 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
223 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
225 * not NULL, it must be a valid pointer to either NULL or a freeable area that
226 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200228int 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 +0200229{
230 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100231 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 int port, end;
233
234 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200235
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100238 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
240 str = next;
241 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100242 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 *next++ = 0;
244 }
245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200247 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200248 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100249 if (!ss2)
250 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100252 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100258 if (!port || !end) {
259 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
260 goto fail;
261 }
262
Emeric Bruned760922010-10-22 17:59:25 +0200263 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
267
268 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200269 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200270 goto fail;
271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100273 else if (ss2->ss_family == AF_UNSPEC) {
274 socklen_t addr_len;
275
276 /* We want to attach to an already bound fd whose number
277 * is in the addr part of ss2 when cast to sockaddr_in.
278 * Note that by definition there is a single listener.
279 * We still have to determine the address family to
280 * register the correct protocol.
281 */
282 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
283 addr_len = sizeof(*ss2);
284 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
285 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
286 goto fail;
287 }
288
289 port = end = get_host_port(ss2);
290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100292 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200293 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100294
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200296 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100297 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200298 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
299 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200300 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301
Willy Tarreau40aa0702013-03-10 23:51:38 +0100302 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200303 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100304 l->state = LI_INIT;
305
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100306 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100308 tcpv4_add_listener(l);
309 }
Emeric Bruned760922010-10-22 17:59:25 +0200310 else if (ss.ss_family == AF_INET6) {
311 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
312 tcpv6_add_listener(l);
313 }
314 else {
Emeric Bruned760922010-10-22 17:59:25 +0200315 uxst_add_listener(l);
316 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200318 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100319 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 } /* end for(port) */
321 } /* end while(next) */
322 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200323 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324 fail:
325 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200326 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327}
328
William Lallemand6e62fb62015-04-28 16:55:23 +0200329/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100330 * Report an error in <msg> when there are too many arguments. This version is
331 * intended to be used by keyword parsers so that the message will be included
332 * into the general error message. The index is the current keyword in args.
333 * Return 0 if the number of argument is correct, otherwise build a message and
334 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
335 * message may also be null, it will simply not be produced (useful to check only).
336 * <msg> and <err_code> are only affected on error.
337 */
338int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
339{
340 int i;
341
342 if (!*args[index + maxarg + 1])
343 return 0;
344
345 if (msg) {
346 *msg = NULL;
347 memprintf(msg, "%s", args[0]);
348 for (i = 1; i <= index; i++)
349 memprintf(msg, "%s %s", *msg, args[i]);
350
351 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
352 }
353 if (err_code)
354 *err_code |= ERR_ALERT | ERR_FATAL;
355
356 return 1;
357}
358
359/*
360 * same as too_many_args_idx with a 0 index
361 */
362int too_many_args(int maxarg, char **args, char **msg, int *err_code)
363{
364 return too_many_args_idx(maxarg, 0, args, msg, err_code);
365}
366
367/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200368 * Report a fatal Alert when there is too much arguments
369 * The index is the current keyword in args
370 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
371 * Fill err_code with an ERR_ALERT and an ERR_FATAL
372 */
373int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
374{
375 char *kw = NULL;
376 int i;
377
378 if (!*args[index + maxarg + 1])
379 return 0;
380
381 memprintf(&kw, "%s", args[0]);
382 for (i = 1; i <= index; i++) {
383 memprintf(&kw, "%s %s", kw, args[i]);
384 }
385
386 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
387 free(kw);
388 *err_code |= ERR_ALERT | ERR_FATAL;
389 return 1;
390}
391
392/*
393 * same as alertif_too_many_args_idx with a 0 index
394 */
395int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
396{
397 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
398}
399
Willy Tarreau620408f2016-10-21 16:37:51 +0200400/* Report a warning if a rule is placed after a 'tcp-request session' rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
403int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
404{
405 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200413/* Report a warning if a rule is placed after a 'tcp-request content' rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
416int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
417{
418 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
Willy Tarreau61d18892009-03-31 10:49:21 +0200426/* Report a warning if a rule is placed after a 'block' rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200431 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
433 file, line, arg);
434 return 1;
435 }
436 return 0;
437}
438
Willy Tarreau5002f572014-04-23 01:32:02 +0200439/* Report a warning if a rule is placed after an 'http_request' rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
442int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
443{
444 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
Willy Tarreau61d18892009-03-31 10:49:21 +0200452/* Report a warning if a rule is placed after a reqrewrite rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100455int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200456{
457 if (proxy->req_exp) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
465/* Report a warning if a rule is placed after a reqadd rule.
466 * Return 1 if the warning has been emitted, otherwise 0.
467 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100468int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200469{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100470 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200471 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
472 file, line, arg);
473 return 1;
474 }
475 return 0;
476}
477
478/* Report a warning if a rule is placed after a redirect rule.
479 * Return 1 if the warning has been emitted, otherwise 0.
480 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
484 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
485 file, line, arg);
486 return 1;
487 }
488 return 0;
489}
490
491/* Report a warning if a rule is placed after a 'use_backend' rule.
492 * Return 1 if the warning has been emitted, otherwise 0.
493 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100494int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200495{
496 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
497 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
498 file, line, arg);
499 return 1;
500 }
501 return 0;
502}
503
Willy Tarreauee445d92014-04-23 01:39:04 +0200504/* Report a warning if a rule is placed after a 'use-server' rule.
505 * Return 1 if the warning has been emitted, otherwise 0.
506 */
507int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
508{
509 if (!LIST_ISEMPTY(&proxy->server_rules)) {
510 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
511 file, line, arg);
512 return 1;
513 }
514 return 0;
515}
516
Willy Tarreaud39ad442016-11-25 15:16:12 +0100517/* report a warning if a redirect rule is dangerously placed */
518int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200519{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100520 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200521 warnif_rule_after_use_server(proxy, file, line, arg);
522}
523
Willy Tarreaud39ad442016-11-25 15:16:12 +0100524/* report a warning if a reqadd rule is dangerously placed */
525int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200526{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100527 return warnif_rule_after_redirect(proxy, file, line, arg) ||
528 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200529}
530
Willy Tarreaud39ad442016-11-25 15:16:12 +0100531/* report a warning if a reqxxx rule is dangerously placed */
532int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200533{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100534 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
535 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200536}
537
538/* report a warning if an http-request rule is dangerously placed */
539int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
540{
Willy Tarreau61d18892009-03-31 10:49:21 +0200541 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200543}
544
Willy Tarreaud39ad442016-11-25 15:16:12 +0100545/* report a warning if a block rule is dangerously placed */
546int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200547{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100548 return warnif_rule_after_http_req(proxy, file, line, arg) ||
549 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200550}
551
Willy Tarreaud39ad442016-11-25 15:16:12 +0100552/* report a warning if a "tcp request content" rule is dangerously placed */
553int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200554{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100555 return warnif_rule_after_block(proxy, file, line, arg) ||
556 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200557}
558
Willy Tarreaud39ad442016-11-25 15:16:12 +0100559/* report a warning if a "tcp request session" rule is dangerously placed */
560int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200561{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100562 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
563 warnif_misplaced_tcp_cont(proxy, file, line, arg);
564}
565
566/* report a warning if a "tcp request connection" rule is dangerously placed */
567int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
568{
569 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
570 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200571}
572
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573/* Report it if a request ACL condition uses some keywords that are incompatible
574 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
575 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
576 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100577 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100578static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100579{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100580 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200581 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100582
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100583 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100584 return 0;
585
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100586 acl = acl_cond_conflicts(cond, where);
587 if (acl) {
588 if (acl->name && *acl->name)
589 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
590 file, line, acl->name, sample_ckp_names(where));
591 else
592 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 +0200593 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100594 return ERR_WARN;
595 }
596 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100597 return 0;
598
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100599 if (acl->name && *acl->name)
600 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200601 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100602 else
603 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200604 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100605 return ERR_WARN;
606}
607
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200609 * parse a line in a <global> section. Returns the error code, 0 if OK, or
610 * any combination of :
611 * - ERR_ABORT: must abort ASAP
612 * - ERR_FATAL: we can continue parsing but not start the service
613 * - ERR_WARN: a warning has been emitted
614 * - ERR_ALERT: an alert has been emitted
615 * Only the two first ones can stop processing, the two others are just
616 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200618int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619{
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200621 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622
623 if (!strcmp(args[0], "global")) { /* new section */
624 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200625 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627 }
628 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200629 if (alertif_too_many_args(0, file, linenum, args, &err_code))
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 global.mode |= MODE_DAEMON;
632 }
633 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200634 if (alertif_too_many_args(0, file, linenum, args, &err_code))
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 global.mode |= MODE_DEBUG;
637 }
638 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(0, file, linenum, args, &err_code))
640 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100641 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200643 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200644 if (alertif_too_many_args(0, file, linenum, args, &err_code))
645 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100646 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200649 if (alertif_too_many_args(0, file, linenum, args, &err_code))
650 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100651 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100653 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200654 if (alertif_too_many_args(0, file, linenum, args, &err_code))
655 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100656 global.tune.options &= ~GTUNE_USE_SPLICE;
657 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200658 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200661 global.tune.options &= ~GTUNE_USE_GAI;
662 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000663 else if (!strcmp(args[0], "noreuseport")) {
664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
666 global.tune.options &= ~GTUNE_USE_REUSEPORT;
667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(0, file, linenum, args, &err_code))
670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 global.mode |= MODE_QUIET;
672 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200673 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200674 if (alertif_too_many_args(1, file, linenum, args, &err_code))
675 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200676 if (global.tune.maxpollevents != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200685 }
686 global.tune.maxpollevents = atol(args[1]);
687 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100688 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200689 if (alertif_too_many_args(1, file, linenum, args, &err_code))
690 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100691 if (global.tune.maxaccept != 0) {
692 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT;
694 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100695 }
696 if (*(args[1]) == 0) {
697 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 err_code |= ERR_ALERT | ERR_FATAL;
699 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100700 }
701 global.tune.maxaccept = atol(args[1]);
702 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200703 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
705 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200706 if (*(args[1]) == 0) {
707 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711 global.tune.chksize = atol(args[1]);
712 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100713 else if (!strcmp(args[0], "tune.recv_enough")) {
714 if (alertif_too_many_args(1, file, linenum, args, &err_code))
715 goto out;
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.tune.recv_enough = atol(args[1]);
722 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100723 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200724 if (alertif_too_many_args(1, file, linenum, args, &err_code))
725 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.buf_limit = atol(args[1]);
732 if (global.tune.buf_limit) {
733 if (global.tune.buf_limit < 3)
734 global.tune.buf_limit = 3;
735 if (global.tune.buf_limit <= global.tune.reserved_bufs)
736 global.tune.buf_limit = global.tune.reserved_bufs + 1;
737 }
738 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100739 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200740 if (alertif_too_many_args(1, file, linenum, args, &err_code))
741 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747 global.tune.reserved_bufs = atol(args[1]);
748 if (global.tune.reserved_bufs < 2)
749 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100750 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
751 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100752 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200753 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200754 if (alertif_too_many_args(1, file, linenum, args, &err_code))
755 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200756 if (*(args[1]) == 0) {
757 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
760 }
761 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200762 if (global.tune.bufsize <= 0) {
763 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100767 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100768 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200769 }
770 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200771 if (alertif_too_many_args(1, file, linenum, args, &err_code))
772 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200773 if (*(args[1]) == 0) {
774 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
778 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200779 if (global.tune.maxrewrite < 0) {
780 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
783 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200784 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100785 else if (!strcmp(args[0], "tune.idletimer")) {
786 unsigned int idle;
787 const char *res;
788
William Lallemand1a748ae2015-05-19 16:37:23 +0200789 if (alertif_too_many_args(1, file, linenum, args, &err_code))
790 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796
797 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
798 if (res) {
799 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
800 file, linenum, *res, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804
805 if (idle > 65535) {
806 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.idle_timer = idle;
811 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100812 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200813 if (alertif_too_many_args(1, file, linenum, args, &err_code))
814 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100815 if (global.tune.client_rcvbuf != 0) {
816 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT;
818 goto out;
819 }
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.client_rcvbuf = atol(args[1]);
826 }
827 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200828 if (alertif_too_many_args(1, file, linenum, args, &err_code))
829 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100830 if (global.tune.server_rcvbuf != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
832 err_code |= ERR_ALERT;
833 goto out;
834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
839 }
840 global.tune.server_rcvbuf = atol(args[1]);
841 }
842 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200843 if (alertif_too_many_args(1, file, linenum, args, &err_code))
844 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100845 if (global.tune.client_sndbuf != 0) {
846 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT;
848 goto out;
849 }
850 if (*(args[1]) == 0) {
851 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
855 global.tune.client_sndbuf = atol(args[1]);
856 }
857 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100860 if (global.tune.server_sndbuf != 0) {
861 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT;
863 goto out;
864 }
865 if (*(args[1]) == 0) {
866 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
870 global.tune.server_sndbuf = atol(args[1]);
871 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200872 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200873 if (alertif_too_many_args(1, file, linenum, args, &err_code))
874 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200875 if (*(args[1]) == 0) {
876 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 global.tune.pipesize = atol(args[1]);
881 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100882 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200883 if (alertif_too_many_args(1, file, linenum, args, &err_code))
884 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890 global.tune.cookie_len = atol(args[1]) + 1;
891 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200892 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200893 if (alertif_too_many_args(1, file, linenum, args, &err_code))
894 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200895 if (*(args[1]) == 0) {
896 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899 }
900 global.tune.max_http_hdr = atol(args[1]);
901 }
William Lallemandf3747832012-11-09 12:33:10 +0100902 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200903 if (alertif_too_many_args(1, file, linenum, args, &err_code))
904 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100905 if (*args[1]) {
906 global.tune.comp_maxlevel = atoi(args[1]);
907 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
908 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
909 file, linenum, args[0]);
910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
913 } else {
914 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
915 file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200920 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
921 if (*args[1]) {
922 global.tune.pattern_cache = atoi(args[1]);
923 if (global.tune.pattern_cache < 0) {
924 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
925 file, linenum, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
928 }
929 } else {
930 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
931 file, linenum, args[0]);
932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
934 }
935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200937 if (alertif_too_many_args(1, file, linenum, args, &err_code))
938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200940 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200941 err_code |= ERR_ALERT;
942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 }
944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100949 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
950 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]);
951 err_code |= ERR_WARN;
952 goto out;
953 }
954
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
956 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200957 if (alertif_too_many_args(1, file, linenum, args, &err_code))
958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200960 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT;
962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100969 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
970 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]);
971 err_code |= ERR_WARN;
972 goto out;
973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 }
Simon Horman98637e52014-06-20 12:30:16 +0900975 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200976 if (alertif_too_many_args(0, file, linenum, args, &err_code))
977 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900978 global.external_check = 1;
979 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200980 /* user/group name handling */
981 else if (!strcmp(args[0], "user")) {
982 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200983 if (alertif_too_many_args(1, file, linenum, args, &err_code))
984 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200985 if (global.uid != 0) {
986 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT;
988 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200989 }
990 errno = 0;
991 ha_user = getpwnam(args[1]);
992 if (ha_user != NULL) {
993 global.uid = (int)ha_user->pw_uid;
994 }
995 else {
996 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 +0200997 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200998 }
999 }
1000 else if (!strcmp(args[0], "group")) {
1001 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001002 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1003 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001004 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001005 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_ALERT;
1007 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001008 }
1009 errno = 0;
1010 ha_group = getgrnam(args[1]);
1011 if (ha_group != NULL) {
1012 global.gid = (int)ha_group->gr_gid;
1013 }
1014 else {
1015 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 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001017 }
1018 }
1019 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001021 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023 if (*(args[1]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027 }
1028 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001029 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1030 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1031 file, linenum, args[0], LONGBITS, global.nbproc);
1032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
1034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 }
1036 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001037 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 if (global.maxconn != 0) {
1040 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_ALERT;
1042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 }
1044 if (*(args[1]) == 0) {
1045 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 }
1049 global.maxconn = atol(args[1]);
1050#ifdef SYSTEM_MAXCONN
1051 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1052 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);
1053 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 }
1056#endif /* SYSTEM_MAXCONN */
1057 }
Emeric Brun850efd52014-01-29 12:24:34 +01001058 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001059 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1060 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001061 if (*(args[1]) == 0) {
1062 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066 if (strcmp(args[1],"none") == 0)
1067 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1068 else if (strcmp(args[1],"required") == 0)
1069 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1070 else {
1071 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001076 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001077 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1078 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001079 if (global.cps_lim != 0) {
1080 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1081 err_code |= ERR_ALERT;
1082 goto out;
1083 }
1084 if (*(args[1]) == 0) {
1085 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089 global.cps_lim = atol(args[1]);
1090 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001091 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001092 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1093 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001094 if (global.sps_lim != 0) {
1095 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1096 err_code |= ERR_ALERT;
1097 goto out;
1098 }
1099 if (*(args[1]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
1104 global.sps_lim = atol(args[1]);
1105 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001106 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001107 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1108 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001109 if (global.ssl_lim != 0) {
1110 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT;
1112 goto out;
1113 }
1114 if (*(args[1]) == 0) {
1115 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1116 err_code |= ERR_ALERT | ERR_FATAL;
1117 goto out;
1118 }
1119 global.ssl_lim = atol(args[1]);
1120 }
William Lallemandd85f9172012-11-09 17:05:39 +01001121 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001122 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1123 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
1128 }
1129 global.comp_rate_lim = atoi(args[1]) * 1024;
1130 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001131 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001132 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1133 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001134 if (global.maxpipes != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
1137 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001143 }
1144 global.maxpipes = atol(args[1]);
1145 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001146 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001147 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1148 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001149 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 }
William Lallemande3a7d992012-11-20 11:25:20 +01001154 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001155 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001156 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001159 if (*(args[1]) == 0) {
1160 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
1164 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001165 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001166 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1167 err_code |= ERR_ALERT | ERR_FATAL;
1168 goto out;
1169 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001170 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001171
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001173 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 if (global.rlimit_nofile != 0) {
1176 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001177 err_code |= ERR_ALERT;
1178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 }
1180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 }
1185 global.rlimit_nofile = atol(args[1]);
1186 }
1187 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001188 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 if (global.chroot != NULL) {
1191 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001192 err_code |= ERR_ALERT;
1193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001194 }
1195 if (*(args[1]) == 0) {
1196 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 }
1200 global.chroot = strdup(args[1]);
1201 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001202 else if (!strcmp(args[0], "description")) {
1203 int i, len=0;
1204 char *d;
1205
1206 if (!*args[1]) {
1207 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1208 file, linenum, args[0]);
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 goto out;
1211 }
1212
Willy Tarreau348acfe2014-04-14 15:00:39 +02001213 for (i = 1; *args[i]; i++)
1214 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001215
1216 if (global.desc)
1217 free(global.desc);
1218
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001219 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001220
Willy Tarreau348acfe2014-04-14 15:00:39 +02001221 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1222 for (i = 2; *args[i]; i++)
1223 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001224 }
1225 else if (!strcmp(args[0], "node")) {
1226 int i;
1227 char c;
1228
William Lallemand1a748ae2015-05-19 16:37:23 +02001229 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1230 goto out;
1231
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001232 for (i=0; args[1][i]; i++) {
1233 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001234 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1235 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001236 break;
1237 }
1238
1239 if (!i || args[1][i]) {
1240 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1241 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1242 file, linenum, args[0]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246
1247 if (global.node)
1248 free(global.node);
1249
1250 global.node = strdup(args[1]);
1251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001253 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 if (global.pidfile != NULL) {
1256 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001257 err_code |= ERR_ALERT;
1258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001259 }
1260 if (*(args[1]) == 0) {
1261 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 }
1265 global.pidfile = strdup(args[1]);
1266 }
Emeric Bruned760922010-10-22 17:59:25 +02001267 else if (!strcmp(args[0], "unix-bind")) {
1268 int cur_arg = 1;
1269 while (*(args[cur_arg])) {
1270 if (!strcmp(args[cur_arg], "prefix")) {
1271 if (global.unix_bind.prefix != NULL) {
1272 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1273 err_code |= ERR_ALERT;
1274 cur_arg += 2;
1275 continue;
1276 }
1277
1278 if (*(args[cur_arg+1]) == 0) {
1279 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282 }
1283 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1284 cur_arg += 2;
1285 continue;
1286 }
1287
1288 if (!strcmp(args[cur_arg], "mode")) {
1289
1290 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1291 cur_arg += 2;
1292 continue;
1293 }
1294
1295 if (!strcmp(args[cur_arg], "uid")) {
1296
1297 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1298 cur_arg += 2;
1299 continue;
1300 }
1301
1302 if (!strcmp(args[cur_arg], "gid")) {
1303
1304 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1305 cur_arg += 2;
1306 continue;
1307 }
1308
1309 if (!strcmp(args[cur_arg], "user")) {
1310 struct passwd *user;
1311
1312 user = getpwnam(args[cur_arg + 1]);
1313 if (!user) {
1314 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1315 file, linenum, args[0], args[cur_arg + 1 ]);
1316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
1318 }
1319
1320 global.unix_bind.ux.uid = user->pw_uid;
1321 cur_arg += 2;
1322 continue;
1323 }
1324
1325 if (!strcmp(args[cur_arg], "group")) {
1326 struct group *group;
1327
1328 group = getgrnam(args[cur_arg + 1]);
1329 if (!group) {
1330 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1331 file, linenum, args[0], args[cur_arg + 1 ]);
1332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
1334 }
1335
1336 global.unix_bind.ux.gid = group->gr_gid;
1337 cur_arg += 2;
1338 continue;
1339 }
1340
Willy Tarreaub48f9582011-09-05 01:17:06 +02001341 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001342 file, linenum, args[0]);
1343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
1345 }
1346 }
William Lallemand0f99e342011-10-12 17:50:54 +02001347 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1348 /* delete previous herited or defined syslog servers */
1349 struct logsrv *back;
1350 struct logsrv *tmp;
1351
1352 if (*(args[1]) != 0) {
1353 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357
1358 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1359 LIST_DEL(&tmp->list);
1360 free(tmp);
1361 }
1362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001364 struct sockaddr_storage *sk;
1365 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001366 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001367 int arg = 0;
1368 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001369
William Lallemand1a748ae2015-05-19 16:37:23 +02001370 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1371 goto out;
1372
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 if (*(args[1]) == 0 || *(args[2]) == 0) {
1374 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 }
William Lallemand0f99e342011-10-12 17:50:54 +02001378
Vincent Bernat02779b62016-04-03 13:48:43 +02001379 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001380
Willy Tarreau18324f52014-06-27 18:10:07 +02001381 /* just after the address, a length may be specified */
1382 if (strcmp(args[arg+2], "len") == 0) {
1383 len = atoi(args[arg+3]);
1384 if (len < 80 || len > 65535) {
1385 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1386 file, linenum, args[arg+3]);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
1389 }
1390 logsrv->maxlen = len;
1391
1392 /* skip these two args */
1393 arg += 2;
1394 }
1395 else
1396 logsrv->maxlen = MAX_SYSLOG_LEN;
1397
1398 if (logsrv->maxlen > global.max_syslog_len) {
1399 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001400 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1401 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1402 logline = my_realloc2(logline, global.max_syslog_len + 1);
1403 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001404 }
1405
Dragan Dosen1322d092015-09-22 16:05:32 +02001406 /* after the length, a format may be specified */
1407 if (strcmp(args[arg+2], "format") == 0) {
1408 logsrv->format = get_log_format(args[arg+3]);
1409 if (logsrv->format < 0) {
1410 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1411 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001412 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001413 goto out;
1414 }
1415
1416 /* skip these two args */
1417 arg += 2;
1418 }
1419
David Carlier97880bb2016-04-08 10:35:26 +01001420 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1421 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001422 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001423 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001424
Willy Tarreau18324f52014-06-27 18:10:07 +02001425 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001426 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001427 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001428 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001429 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 }
1431
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001433 if (*(args[arg+3])) {
1434 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001435 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001436 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001437 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001438 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 }
1440 }
1441
William Lallemand0f99e342011-10-12 17:50:54 +02001442 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001443 if (*(args[arg+4])) {
1444 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001445 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001446 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001447 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001448 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001449 }
1450 }
1451
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001452 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001453 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001454 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001455 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001456 free(logsrv);
1457 goto out;
1458 }
1459 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001460
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001461 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001462 if (port1 != port2) {
1463 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1464 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001465 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001466 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001467 goto out;
1468 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001469
William Lallemand0f99e342011-10-12 17:50:54 +02001470 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001471 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001472 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474
William Lallemand0f99e342011-10-12 17:50:54 +02001475 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001476 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001477 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1478 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001479
1480 if (global.log_send_hostname != NULL) {
1481 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1482 err_code |= ERR_ALERT;
1483 goto out;
1484 }
1485
1486 if (*(args[1]))
1487 name = args[1];
1488 else
1489 name = hostname;
1490
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001491 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001492 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001493 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001494 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1495 if (global.server_state_base != NULL) {
1496 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1497 err_code |= ERR_ALERT;
1498 goto out;
1499 }
1500
1501 if (!*(args[1])) {
1502 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1503 err_code |= ERR_FATAL;
1504 goto out;
1505 }
1506
1507 global.server_state_base = strdup(args[1]);
1508 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001509 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1510 if (global.server_state_file != NULL) {
1511 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1512 err_code |= ERR_ALERT;
1513 goto out;
1514 }
1515
1516 if (!*(args[1])) {
1517 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1518 err_code |= ERR_FATAL;
1519 goto out;
1520 }
1521
1522 global.server_state_file = strdup(args[1]);
1523 }
Kevinm48936af2010-12-22 16:08:21 +00001524 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001525 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1526 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001527 if (*(args[1]) == 0) {
1528 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001532 chunk_destroy(&global.log_tag);
1533 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001534 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001535 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001536 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1537 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001538 if (global.spread_checks != 0) {
1539 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001540 err_code |= ERR_ALERT;
1541 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001542 }
1543 if (*(args[1]) == 0) {
1544 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001547 }
1548 global.spread_checks = atol(args[1]);
1549 if (global.spread_checks < 0 || global.spread_checks > 50) {
1550 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001551 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001554 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1555 const char *err;
1556 unsigned int val;
1557
William Lallemand1a748ae2015-05-19 16:37:23 +02001558 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1559 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001560 if (*(args[1]) == 0) {
1561 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1562 err_code |= ERR_ALERT | ERR_FATAL;
1563 goto out;
1564 }
1565
1566 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1567 if (err) {
1568 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1569 err_code |= ERR_ALERT | ERR_FATAL;
1570 }
1571 global.max_spread_checks = val;
1572 if (global.max_spread_checks < 0) {
1573 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1574 err_code |= ERR_ALERT | ERR_FATAL;
1575 }
1576 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001577 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1578#ifdef USE_CPU_AFFINITY
1579 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001580 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001581 unsigned long cpus = 0;
1582
1583 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001584 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001585 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001586 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001587 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001588 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001589 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001590 proc = atol(args[1]);
1591 if (proc >= 1 && proc <= LONGBITS)
1592 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001593 }
1594
1595 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001596 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1597 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001598 err_code |= ERR_ALERT | ERR_FATAL;
1599 goto out;
1600 }
1601
1602 cur_arg = 2;
1603 while (*args[cur_arg]) {
1604 unsigned int low, high;
1605
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001606 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001607 char *dash = strchr(args[cur_arg], '-');
1608
1609 low = high = str2uic(args[cur_arg]);
1610 if (dash)
1611 high = str2uic(dash + 1);
1612
1613 if (high < low) {
1614 unsigned int swap = low;
1615 low = high;
1616 high = swap;
1617 }
1618
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001619 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001620 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001621 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001622 err_code |= ERR_ALERT | ERR_FATAL;
1623 goto out;
1624 }
1625
1626 while (low <= high)
1627 cpus |= 1UL << low++;
1628 }
1629 else {
1630 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1631 file, linenum, args[0], args[cur_arg]);
1632 err_code |= ERR_ALERT | ERR_FATAL;
1633 goto out;
1634 }
1635 cur_arg++;
1636 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001637 for (i = 0; i < LONGBITS; i++)
1638 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001639 global.cpu_map[i] = cpus;
1640#else
1641 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
1644#endif
1645 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001646 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1647 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1648 goto out;
1649
1650 if (*(args[2]) == 0) {
1651 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
1654 }
1655
1656 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1657 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1658 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
1661 }
1662 }
1663 else if (!strcmp(args[0], "unsetenv")) {
1664 int arg;
1665
1666 if (*(args[1]) == 0) {
1667 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
1670 }
1671
1672 for (arg = 1; *args[arg]; arg++) {
1673 if (unsetenv(args[arg]) != 0) {
1674 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
1677 }
1678 }
1679 }
1680 else if (!strcmp(args[0], "resetenv")) {
1681 extern char **environ;
1682 char **env = environ;
1683
1684 /* args contain variable names to keep, one per argument */
1685 while (*env) {
1686 int arg;
1687
1688 /* look for current variable in among all those we want to keep */
1689 for (arg = 1; *args[arg]; arg++) {
1690 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1691 (*env)[strlen(args[arg])] == '=')
1692 break;
1693 }
1694
1695 /* delete this variable */
1696 if (!*args[arg]) {
1697 char *delim = strchr(*env, '=');
1698
1699 if (!delim || delim - *env >= trash.size) {
1700 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1701 err_code |= ERR_ALERT | ERR_FATAL;
1702 goto out;
1703 }
1704
1705 memcpy(trash.str, *env, delim - *env);
1706 trash.str[delim - *env] = 0;
1707
1708 if (unsetenv(trash.str) != 0) {
1709 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
1712 }
1713 }
1714 else
1715 env++;
1716 }
1717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001719 struct cfg_kw_list *kwl;
1720 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001721 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001722
1723 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1724 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1725 if (kwl->kw[index].section != CFG_GLOBAL)
1726 continue;
1727 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001728 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001729 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001730 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001732 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001733 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001734 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001735 err_code |= ERR_WARN;
1736 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001737 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001738 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001739 }
1740 }
1741 }
1742
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001746
Willy Tarreau058e9072009-07-20 09:30:05 +02001747 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001748 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001749 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001750}
1751
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001752void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001754 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 defproxy.mode = PR_MODE_TCP;
1756 defproxy.state = PR_STNEW;
1757 defproxy.maxconn = cfg_maxpconn;
1758 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001759 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001760 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001761
Simon Horman66183002013-02-23 10:16:43 +09001762 defproxy.defsrv.check.inter = DEF_CHKINTR;
1763 defproxy.defsrv.check.fastinter = 0;
1764 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001765 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1766 defproxy.defsrv.agent.fastinter = 0;
1767 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001768 defproxy.defsrv.check.rise = DEF_RISETIME;
1769 defproxy.defsrv.check.fall = DEF_FALLTIME;
1770 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1771 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001772 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001773 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001774 defproxy.defsrv.maxqueue = 0;
1775 defproxy.defsrv.minconn = 0;
1776 defproxy.defsrv.maxconn = 0;
1777 defproxy.defsrv.slowstart = 0;
1778 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1779 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1780 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001781
1782 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001783 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784}
1785
Willy Tarreauade5ec42010-01-28 19:33:49 +01001786
Willy Tarreau63af98d2014-05-18 08:11:41 +02001787/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1788 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1789 * ERR_FATAL in case of error.
1790 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001791static int create_cond_regex_rule(const char *file, int line,
1792 struct proxy *px, int dir, int action, int flags,
1793 const char *cmd, const char *reg, const char *repl,
1794 const char **cond_start)
1795{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001796 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001797 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001798 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001799 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001800 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001801 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001802 int cs;
1803 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001804
1805 if (px == &defproxy) {
1806 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001807 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001808 goto err;
1809 }
1810
1811 if (*reg == 0) {
1812 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001813 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001814 goto err;
1815 }
1816
Christopher Faulet898566e2016-10-26 11:06:28 +02001817 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001818 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001819
Willy Tarreau5321c422010-01-28 20:35:13 +01001820 if (cond_start &&
1821 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001822 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1823 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1824 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001825 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001826 goto err;
1827 }
1828 }
1829 else if (cond_start && **cond_start) {
1830 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1831 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001833 goto err;
1834 }
1835
Willy Tarreau63af98d2014-05-18 08:11:41 +02001836 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001837 (dir == SMP_OPT_DIR_REQ) ?
1838 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1839 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1840 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001841
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001842 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001843 if (!preg) {
1844 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001845 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001846 goto err;
1847 }
1848
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001849 cs = !(flags & REG_ICASE);
1850 cap = !(flags & REG_NOSUB);
1851 error = NULL;
1852 if (!regex_comp(reg, preg, cs, cap, &error)) {
1853 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1854 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001855 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001856 goto err;
1857 }
1858
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001859 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001860 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001861 if (repl && err) {
1862 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1863 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001864 ret_code |= ERR_ALERT | ERR_FATAL;
1865 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001866 }
1867
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001868 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001869 ret_code |= ERR_WARN;
1870
1871 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001872
Willy Tarreau63af98d2014-05-18 08:11:41 +02001873 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001874 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001875 err:
1876 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001877 free(errmsg);
1878 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001879}
1880
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881/*
William Lallemand51097192015-04-14 16:35:22 +02001882 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001883 * Returns the error code, 0 if OK, or any combination of :
1884 * - ERR_ABORT: must abort ASAP
1885 * - ERR_FATAL: we can continue parsing but not start the service
1886 * - ERR_WARN: a warning has been emitted
1887 * - ERR_ALERT: an alert has been emitted
1888 * Only the two first ones can stop processing, the two others are just
1889 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001891int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1892{
1893 static struct peers *curpeers = NULL;
1894 struct peer *newpeer = NULL;
1895 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001896 struct bind_conf *bind_conf;
1897 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001898 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001899 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001900
1901 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001902 if (!*args[1]) {
1903 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001904 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001905 goto out;
1906 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001907
William Lallemand6e62fb62015-04-28 16:55:23 +02001908 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1909 goto out;
1910
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 err = invalid_char(args[1]);
1912 if (err) {
1913 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1914 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001915 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001916 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001917 }
1918
1919 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1920 /*
1921 * If there are two proxies with the same name only following
1922 * combinations are allowed:
1923 */
1924 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001925 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 +02001926 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001927 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001928 }
1929 }
1930
Vincent Bernat02779b62016-04-03 13:48:43 +02001931 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001932 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1933 err_code |= ERR_ALERT | ERR_ABORT;
1934 goto out;
1935 }
1936
1937 curpeers->next = peers;
1938 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001939 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001940 curpeers->conf.line = linenum;
1941 curpeers->last_change = now.tv_sec;
1942 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001943 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001944 }
1945 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001946 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001947 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001948 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001949
1950 if (!*args[2]) {
1951 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1952 file, linenum, args[0]);
1953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
1955 }
1956
1957 err = invalid_char(args[1]);
1958 if (err) {
1959 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1960 file, linenum, *err, args[1]);
1961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
1963 }
1964
Vincent Bernat02779b62016-04-03 13:48:43 +02001965 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001966 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1967 err_code |= ERR_ALERT | ERR_ABORT;
1968 goto out;
1969 }
1970
1971 /* the peers are linked backwards first */
1972 curpeers->count++;
1973 newpeer->next = curpeers->remote;
1974 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001975 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001976 newpeer->conf.line = linenum;
1977
1978 newpeer->last_change = now.tv_sec;
1979 newpeer->id = strdup(args[1]);
1980
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001981 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001982 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001983 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001986 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001987
1988 proto = protocol_by_family(sk->ss_family);
1989 if (!proto || !proto->connect) {
1990 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1991 file, linenum, args[0], args[1]);
1992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
1994 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001995
1996 if (port1 != port2) {
1997 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1998 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
2001 }
2002
Willy Tarreau2aa38802013-02-20 19:20:59 +01002003 if (!port1) {
2004 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2005 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
2008 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002009
Emeric Brun32da3c42010-09-23 18:39:19 +02002010 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002011 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002012 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002013 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002014
Emeric Brun32da3c42010-09-23 18:39:19 +02002015 if (strcmp(newpeer->id, localpeer) == 0) {
2016 /* Current is local peer, it define a frontend */
2017 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002018 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002019
2020 if (!curpeers->peers_fe) {
2021 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2022 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2023 err_code |= ERR_ALERT | ERR_ABORT;
2024 goto out;
2025 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002026
Willy Tarreau237250c2011-07-29 01:49:03 +02002027 init_new_proxy(curpeers->peers_fe);
2028 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002029 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002030 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2031 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002032 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002033
Willy Tarreauc95bad52016-12-22 00:13:31 +01002034 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], &raw_sock);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002035
Willy Tarreau902636f2013-03-10 19:44:48 +01002036 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2037 if (errmsg && *errmsg) {
2038 indent_msg(&errmsg, 2);
2039 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002040 }
2041 else
2042 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2043 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002044 err_code |= ERR_FATAL;
2045 goto out;
2046 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002047
2048 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002049 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002050 l->maxconn = curpeers->peers_fe->maxconn;
2051 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002052 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002053 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002054 l->analysers |= curpeers->peers_fe->fe_req_ana;
2055 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002056 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2057 global.maxsock += l->maxconn;
2058 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002059 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002060 else {
2061 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2062 file, linenum, args[0], args[1],
2063 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2064 err_code |= ERR_FATAL;
2065 goto out;
2066 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002067 }
2068 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002069 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2070 curpeers->state = PR_STSTOPPED;
2071 }
2072 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2073 curpeers->state = PR_STNEW;
2074 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002075 else if (*args[0] != 0) {
2076 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2077 err_code |= ERR_ALERT | ERR_FATAL;
2078 goto out;
2079 }
2080
2081out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002082 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002083 return err_code;
2084}
2085
Baptiste Assmann325137d2015-04-13 23:40:55 +02002086/*
2087 * Parse a <resolvers> section.
2088 * Returns the error code, 0 if OK, or any combination of :
2089 * - ERR_ABORT: must abort ASAP
2090 * - ERR_FATAL: we can continue parsing but not start the service
2091 * - ERR_WARN: a warning has been emitted
2092 * - ERR_ALERT: an alert has been emitted
2093 * Only the two first ones can stop processing, the two others are just
2094 * indicators.
2095 */
2096int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2097{
2098 static struct dns_resolvers *curr_resolvers = NULL;
2099 struct dns_nameserver *newnameserver = NULL;
2100 const char *err;
2101 int err_code = 0;
2102 char *errmsg = NULL;
2103
2104 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2105 if (!*args[1]) {
2106 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2107 err_code |= ERR_ALERT | ERR_ABORT;
2108 goto out;
2109 }
2110
2111 err = invalid_char(args[1]);
2112 if (err) {
2113 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2114 file, linenum, *err, args[0], args[1]);
2115 err_code |= ERR_ALERT | ERR_ABORT;
2116 goto out;
2117 }
2118
2119 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2120 /* Error if two resolvers owns the same name */
2121 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2122 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2123 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2124 err_code |= ERR_ALERT | ERR_ABORT;
2125 }
2126 }
2127
Vincent Bernat02779b62016-04-03 13:48:43 +02002128 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002129 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2130 err_code |= ERR_ALERT | ERR_ABORT;
2131 goto out;
2132 }
2133
2134 /* default values */
2135 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2136 curr_resolvers->conf.file = strdup(file);
2137 curr_resolvers->conf.line = linenum;
2138 curr_resolvers->id = strdup(args[1]);
2139 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002140 /* default hold period for nx, other, refuse and timeout is 30s */
2141 curr_resolvers->hold.nx = 30000;
2142 curr_resolvers->hold.other = 30000;
2143 curr_resolvers->hold.refused = 30000;
2144 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002145 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002146 curr_resolvers->hold.valid = 10000;
2147 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002148 curr_resolvers->resolve_retries = 3;
2149 LIST_INIT(&curr_resolvers->nameserver_list);
2150 LIST_INIT(&curr_resolvers->curr_resolution);
2151 }
2152 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2153 struct sockaddr_storage *sk;
2154 int port1, port2;
2155 struct protocol *proto;
2156
2157 if (!*args[2]) {
2158 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2159 file, linenum, args[0]);
2160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
2162 }
2163
2164 err = invalid_char(args[1]);
2165 if (err) {
2166 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2167 file, linenum, *err, args[1]);
2168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
2171
Baptiste Assmanna315c552015-11-02 22:55:49 +01002172 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2173 /* Error if two resolvers owns the same name */
2174 if (strcmp(newnameserver->id, args[1]) == 0) {
2175 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2176 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 }
2179 }
2180
Vincent Bernat02779b62016-04-03 13:48:43 +02002181 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002182 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2183 err_code |= ERR_ALERT | ERR_ABORT;
2184 goto out;
2185 }
2186
2187 /* the nameservers are linked backward first */
2188 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2189 curr_resolvers->count_nameservers++;
2190 newnameserver->resolvers = curr_resolvers;
2191 newnameserver->conf.file = strdup(file);
2192 newnameserver->conf.line = linenum;
2193 newnameserver->id = strdup(args[1]);
2194
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002195 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002196 if (!sk) {
2197 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
2200 }
2201
2202 proto = protocol_by_family(sk->ss_family);
2203 if (!proto || !proto->connect) {
2204 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2205 file, linenum, args[0], args[1]);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
2208 }
2209
2210 if (port1 != port2) {
2211 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2212 file, linenum, args[0], args[1], args[2]);
2213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
2215 }
2216
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002217 if (!port1 && !port2) {
2218 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2219 file, linenum, args[0], args[1]);
2220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
2222 }
2223
Baptiste Assmann325137d2015-04-13 23:40:55 +02002224 newnameserver->addr = *sk;
2225 }
2226 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2227 const char *res;
2228 unsigned int time;
2229
2230 if (!*args[2]) {
2231 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2232 file, linenum, args[0]);
2233 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
2237 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2238 if (res) {
2239 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2240 file, linenum, *res, args[0]);
2241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
2243 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002244 if (strcmp(args[1], "nx") == 0)
2245 curr_resolvers->hold.nx = time;
2246 else if (strcmp(args[1], "other") == 0)
2247 curr_resolvers->hold.other = time;
2248 else if (strcmp(args[1], "refused") == 0)
2249 curr_resolvers->hold.refused = time;
2250 else if (strcmp(args[1], "timeout") == 0)
2251 curr_resolvers->hold.timeout = time;
2252 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002253 curr_resolvers->hold.valid = time;
2254 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002255 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2256 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
2259 }
2260
2261 }
2262 else if (strcmp(args[0], "resolve_retries") == 0) {
2263 if (!*args[1]) {
2264 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2265 file, linenum, args[0]);
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
2268 }
2269 curr_resolvers->resolve_retries = atoi(args[1]);
2270 }
2271 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002272 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002273 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2274 file, linenum, args[0]);
2275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
2277 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002278 else if (strcmp(args[1], "retry") == 0) {
2279 const char *res;
2280 unsigned int timeout_retry;
2281
2282 if (!*args[2]) {
2283 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2284 file, linenum, args[0], args[1]);
2285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
2287 }
2288 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2289 if (res) {
2290 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2291 file, linenum, *res, args[0], args[1]);
2292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
2294 }
2295 curr_resolvers->timeout.retry = timeout_retry;
2296 }
2297 else {
2298 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2299 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002303 } /* neither "nameserver" nor "resolvers" */
2304 else if (*args[0] != 0) {
2305 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 out:
2311 free(errmsg);
2312 return err_code;
2313}
Simon Horman0d16a402015-01-30 11:22:58 +09002314
2315/*
William Lallemand51097192015-04-14 16:35:22 +02002316 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002317 * Returns the error code, 0 if OK, or any combination of :
2318 * - ERR_ABORT: must abort ASAP
2319 * - ERR_FATAL: we can continue parsing but not start the service
2320 * - ERR_WARN: a warning has been emitted
2321 * - ERR_ALERT: an alert has been emitted
2322 * Only the two first ones can stop processing, the two others are just
2323 * indicators.
2324 */
2325int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2326{
2327 static struct mailers *curmailers = NULL;
2328 struct mailer *newmailer = NULL;
2329 const char *err;
2330 int err_code = 0;
2331 char *errmsg = NULL;
2332
2333 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2334 if (!*args[1]) {
2335 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2336 err_code |= ERR_ALERT | ERR_ABORT;
2337 goto out;
2338 }
2339
2340 err = invalid_char(args[1]);
2341 if (err) {
2342 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2343 file, linenum, *err, args[0], args[1]);
2344 err_code |= ERR_ALERT | ERR_ABORT;
2345 goto out;
2346 }
2347
2348 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2349 /*
2350 * If there are two proxies with the same name only following
2351 * combinations are allowed:
2352 */
2353 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002354 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 +09002355 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002356 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002357 }
2358 }
2359
Vincent Bernat02779b62016-04-03 13:48:43 +02002360 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002361 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2362 err_code |= ERR_ALERT | ERR_ABORT;
2363 goto out;
2364 }
2365
2366 curmailers->next = mailers;
2367 mailers = curmailers;
2368 curmailers->conf.file = strdup(file);
2369 curmailers->conf.line = linenum;
2370 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002371 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2372 * But need enough time so that timeouts don't occur
2373 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002374 }
2375 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2376 struct sockaddr_storage *sk;
2377 int port1, port2;
2378 struct protocol *proto;
2379
2380 if (!*args[2]) {
2381 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2382 file, linenum, args[0]);
2383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
2385 }
2386
2387 err = invalid_char(args[1]);
2388 if (err) {
2389 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2390 file, linenum, *err, args[1]);
2391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
2393 }
2394
Vincent Bernat02779b62016-04-03 13:48:43 +02002395 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002396 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2397 err_code |= ERR_ALERT | ERR_ABORT;
2398 goto out;
2399 }
2400
2401 /* the mailers are linked backwards first */
2402 curmailers->count++;
2403 newmailer->next = curmailers->mailer_list;
2404 curmailers->mailer_list = newmailer;
2405 newmailer->mailers = curmailers;
2406 newmailer->conf.file = strdup(file);
2407 newmailer->conf.line = linenum;
2408
2409 newmailer->id = strdup(args[1]);
2410
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002411 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002412 if (!sk) {
2413 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
2416 }
2417
2418 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002419 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2420 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002421 file, linenum, args[0], args[1]);
2422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
2424 }
2425
2426 if (port1 != port2) {
2427 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2428 file, linenum, args[0], args[1], args[2]);
2429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
2431 }
2432
2433 if (!port1) {
2434 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2435 file, linenum, args[0], args[1], args[2]);
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439
2440 newmailer->addr = *sk;
2441 newmailer->proto = proto;
2442 newmailer->xprt = &raw_sock;
2443 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002444 }
2445 else if (strcmp(args[0], "timeout") == 0) {
2446 if (!*args[1]) {
2447 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2448 file, linenum, args[0]);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452 else if (strcmp(args[1], "mail") == 0) {
2453 const char *res;
2454 unsigned int timeout_mail;
2455 if (!*args[2]) {
2456 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2457 file, linenum, args[0], args[1]);
2458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
2460 }
2461 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2462 if (res) {
2463 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2464 file, linenum, *res, args[0]);
2465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
2467 }
2468 if (timeout_mail <= 0) {
2469 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473 curmailers->timeout.mail = timeout_mail;
2474 } else {
2475 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2476 file, linenum, args[0], args[1]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480 }
Simon Horman0d16a402015-01-30 11:22:58 +09002481 else if (*args[0] != 0) {
2482 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487out:
2488 free(errmsg);
2489 return err_code;
2490}
2491
Simon Horman9dc49962015-01-30 11:22:59 +09002492static void free_email_alert(struct proxy *p)
2493{
2494 free(p->email_alert.mailers.name);
2495 p->email_alert.mailers.name = NULL;
2496 free(p->email_alert.from);
2497 p->email_alert.from = NULL;
2498 free(p->email_alert.to);
2499 p->email_alert.to = NULL;
2500 free(p->email_alert.myhostname);
2501 p->email_alert.myhostname = NULL;
2502}
2503
Willy Tarreau3842f002009-06-14 11:39:52 +02002504int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505{
2506 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002507 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002508 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002509 int rc;
2510 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002511 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002512 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002513 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002514 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002515 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516
Willy Tarreau977b8e42006-12-29 14:19:17 +01002517 if (!strcmp(args[0], "listen"))
2518 rc = PR_CAP_LISTEN;
2519 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002520 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002521 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002522 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002523 else
2524 rc = PR_CAP_NONE;
2525
2526 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 if (!*args[1]) {
2528 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002529 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_ABORT;
2532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002534
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002535 err = invalid_char(args[1]);
2536 if (err) {
2537 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2538 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002540 }
2541
Willy Tarreau8f50b682015-05-26 11:45:02 +02002542 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2543 if (curproxy) {
2544 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2545 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2546 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002548 }
2549
Vincent Bernat02779b62016-04-03 13:48:43 +02002550 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_ABORT;
2553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002555
Willy Tarreau97cb7802010-01-03 20:23:58 +01002556 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 curproxy->next = proxy;
2558 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002559 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2560 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002561 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002564 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565
William Lallemand6e62fb62015-04-28 16:55:23 +02002566 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2567 if (curproxy->cap & PR_CAP_FE)
2568 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
2571
2572 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002573 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002574 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002575
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002578 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002579 curproxy->no_options = defproxy.no_options;
2580 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002581 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002582 curproxy->except_net = defproxy.except_net;
2583 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002584 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002585 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002587 if (defproxy.fwdfor_hdr_len) {
2588 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2589 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2590 }
2591
Willy Tarreaub86db342009-11-30 11:50:16 +01002592 if (defproxy.orgto_hdr_len) {
2593 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2594 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2595 }
2596
Mark Lamourinec2247f02012-01-04 13:02:01 -05002597 if (defproxy.server_id_hdr_len) {
2598 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2599 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2600 }
2601
Willy Tarreau977b8e42006-12-29 14:19:17 +01002602 if (curproxy->cap & PR_CAP_FE) {
2603 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002604 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002605 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002606
2607 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002608 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2609 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002610
2611 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613
Willy Tarreau977b8e42006-12-29 14:19:17 +01002614 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002615 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002616 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002617 curproxy->fullconn = defproxy.fullconn;
2618 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002619 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002620 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002622 if (defproxy.check_req) {
2623 curproxy->check_req = calloc(1, defproxy.check_len);
2624 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2625 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002628 if (defproxy.expect_str) {
2629 curproxy->expect_str = strdup(defproxy.expect_str);
2630 if (defproxy.expect_regex) {
2631 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002632 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2633 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002634 }
2635 }
2636
Willy Tarreau67402132012-05-31 20:40:20 +02002637 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638 if (defproxy.cookie_name)
2639 curproxy->cookie_name = strdup(defproxy.cookie_name);
2640 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002641 if (defproxy.cookie_domain)
2642 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002643
Willy Tarreau31936852010-10-06 16:59:56 +02002644 if (defproxy.cookie_maxidle)
2645 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2646
2647 if (defproxy.cookie_maxlife)
2648 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2649
Emeric Brun647caf12009-06-30 17:57:00 +02002650 if (defproxy.rdp_cookie_name)
2651 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2652 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2653
Willy Tarreau01732802007-11-01 22:48:15 +01002654 if (defproxy.url_param_name)
2655 curproxy->url_param_name = strdup(defproxy.url_param_name);
2656 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002657
Benoitaffb4812009-03-25 13:02:10 +01002658 if (defproxy.hh_name)
2659 curproxy->hh_name = strdup(defproxy.hh_name);
2660 curproxy->hh_len = defproxy.hh_len;
2661 curproxy->hh_match_domain = defproxy.hh_match_domain;
2662
Willy Tarreauef9a3602012-12-08 22:29:20 +01002663 if (defproxy.conn_src.iface_name)
2664 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2665 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002666 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002667#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002668 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002669#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002670 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002673 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002674 if (defproxy.capture_name)
2675 curproxy->capture_name = strdup(defproxy.capture_name);
2676 curproxy->capture_namelen = defproxy.capture_namelen;
2677 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679
Willy Tarreau977b8e42006-12-29 14:19:17 +01002680 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002681 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002682 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002683 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002684 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002685 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002686 curproxy->mon_net = defproxy.mon_net;
2687 curproxy->mon_mask = defproxy.mon_mask;
2688 if (defproxy.monitor_uri)
2689 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2690 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002691 if (defproxy.defbe.name)
2692 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002693
2694 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002695 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2696 if (curproxy->conf.logformat_string &&
2697 curproxy->conf.logformat_string != default_http_log_format &&
2698 curproxy->conf.logformat_string != default_tcp_log_format &&
2699 curproxy->conf.logformat_string != clf_http_log_format)
2700 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2701
2702 if (defproxy.conf.lfs_file) {
2703 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2704 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2705 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002706
2707 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2708 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2709 if (curproxy->conf.logformat_sd_string &&
2710 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2711 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2712
2713 if (defproxy.conf.lfsd_file) {
2714 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2715 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2716 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 }
2718
2719 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002720 curproxy->timeout.connect = defproxy.timeout.connect;
2721 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002722 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002723 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002724 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002725 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002726 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002727 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002728 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002729 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002730 }
2731
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002733 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002734
2735 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002736 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002737 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002738 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002739 LIST_INIT(&node->list);
2740 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2741 }
2742
Willy Tarreau62a61232013-04-12 18:13:46 +02002743 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2744 if (curproxy->conf.uniqueid_format_string)
2745 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2746
Dragan Dosen43885c72015-10-01 13:18:13 +02002747 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002748
Willy Tarreau62a61232013-04-12 18:13:46 +02002749 if (defproxy.conf.uif_file) {
2750 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2751 curproxy->conf.uif_line = defproxy.conf.uif_line;
2752 }
William Lallemanda73203e2012-03-12 12:48:57 +01002753
2754 /* copy default header unique id */
2755 if (defproxy.header_unique_id)
2756 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2757
William Lallemand82fe75c2012-10-23 10:25:10 +02002758 /* default compression options */
2759 if (defproxy.comp != NULL) {
2760 curproxy->comp = calloc(1, sizeof(struct comp));
2761 curproxy->comp->algos = defproxy.comp->algos;
2762 curproxy->comp->types = defproxy.comp->types;
2763 }
2764
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002766 curproxy->conf.used_listener_id = EB_ROOT;
2767 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002768
Simon Horman98637e52014-06-20 12:30:16 +09002769 if (defproxy.check_path)
2770 curproxy->check_path = strdup(defproxy.check_path);
2771 if (defproxy.check_command)
2772 curproxy->check_command = strdup(defproxy.check_command);
2773
Simon Horman9dc49962015-01-30 11:22:59 +09002774 if (defproxy.email_alert.mailers.name)
2775 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2776 if (defproxy.email_alert.from)
2777 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2778 if (defproxy.email_alert.to)
2779 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2780 if (defproxy.email_alert.myhostname)
2781 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002782 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002783 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002784
Willy Tarreau93893792009-07-23 13:19:11 +02002785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 }
2787 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2788 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002789 /* FIXME-20070101: we should do this too at the end of the
2790 * config parsing to free all default values.
2791 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002792 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2793 err_code |= ERR_ABORT;
2794 goto out;
2795 }
2796
Willy Tarreaua534fea2008-08-03 12:19:50 +02002797 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002798 free(defproxy.check_command);
2799 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002800 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002801 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002802 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002803 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002804 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002805 free(defproxy.capture_name);
2806 free(defproxy.monitor_uri);
2807 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002808 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002809 free(defproxy.fwdfor_hdr_name);
2810 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002811 free(defproxy.orgto_hdr_name);
2812 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002813 free(defproxy.server_id_hdr_name);
2814 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002815 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002816 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002817 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002818 free(defproxy.expect_regex);
2819 defproxy.expect_regex = NULL;
2820 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002821
Willy Tarreau62a61232013-04-12 18:13:46 +02002822 if (defproxy.conf.logformat_string != default_http_log_format &&
2823 defproxy.conf.logformat_string != default_tcp_log_format &&
2824 defproxy.conf.logformat_string != clf_http_log_format)
2825 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002826
Willy Tarreau62a61232013-04-12 18:13:46 +02002827 free(defproxy.conf.uniqueid_format_string);
2828 free(defproxy.conf.lfs_file);
2829 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002830 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002831 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002832
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002833 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2834 free(defproxy.conf.logformat_sd_string);
2835 free(defproxy.conf.lfsd_file);
2836
Willy Tarreaua534fea2008-08-03 12:19:50 +02002837 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002838 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002839
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 /* we cannot free uri_auth because it might already be used */
2841 init_default_instance();
2842 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002843 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2844 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002845 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 }
2848 else if (curproxy == NULL) {
2849 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002853
2854 /* update the current file and line being parsed */
2855 curproxy->conf.args.file = curproxy->conf.file;
2856 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002857
2858 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002859 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2860 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2861 if (err_code & ERR_FATAL)
2862 goto out;
2863 }
2864 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002865 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002866 int cur_arg;
2867
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 if (curproxy == &defproxy) {
2869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002873 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875
Willy Tarreau24709282013-03-10 21:32:12 +01002876 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002877 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002882
Willy Tarreauc95bad52016-12-22 00:13:31 +01002883 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], &raw_sock);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002884
2885 /* use default settings for unix sockets */
2886 bind_conf->ux.uid = global.unix_bind.ux.uid;
2887 bind_conf->ux.gid = global.unix_bind.ux.gid;
2888 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002889
2890 /* NOTE: the following line might create several listeners if there
2891 * are comma-separated IPs or port ranges. So all further processing
2892 * will have to be applied to all listeners created after last_listen.
2893 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002894 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2895 if (errmsg && *errmsg) {
2896 indent_msg(&errmsg, 2);
2897 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002898 }
2899 else
2900 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2901 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002905
Willy Tarreau4348fad2012-09-20 16:48:07 +02002906 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2907 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002908 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002909 }
2910
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002911 cur_arg = 2;
2912 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002913 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002914 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002915 char *err;
2916
Willy Tarreau26982662012-09-12 23:17:10 +02002917 kw = bind_find_kw(args[cur_arg]);
2918 if (kw) {
2919 char *err = NULL;
2920 int code;
2921
2922 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002923 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2924 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002925 cur_arg += 1 + kw->skip ;
2926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
2929
Willy Tarreau4348fad2012-09-20 16:48:07 +02002930 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002931 err_code |= code;
2932
2933 if (code) {
2934 if (err && *err) {
2935 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002936 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002937 }
2938 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002939 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2940 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002941 if (code & ERR_FATAL) {
2942 free(err);
2943 cur_arg += 1 + kw->skip;
2944 goto out;
2945 }
2946 }
2947 free(err);
2948 cur_arg += 1 + kw->skip;
2949 continue;
2950 }
2951
Willy Tarreau8638f482012-09-18 18:01:17 +02002952 err = NULL;
2953 if (!bind_dumped) {
2954 bind_dump_kws(&err);
2955 indent_msg(&err, 4);
2956 bind_dumped = 1;
2957 }
2958
2959 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2960 file, linenum, args[0], args[1], args[cur_arg],
2961 err ? " Registered keywords :" : "", err ? err : "");
2962 free(err);
2963
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002966 }
Willy Tarreau93893792009-07-23 13:19:11 +02002967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968 }
2969 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002970 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2972 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002978
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 /* flush useless bits */
2980 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002983 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002986
William Lallemanddf1425a2015-04-28 20:17:49 +02002987 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2988 goto out;
2989
Willy Tarreau1c47f852006-07-09 08:22:27 +02002990 if (!*args[1]) {
2991 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2992 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002995 }
2996
Willy Tarreaua534fea2008-08-03 12:19:50 +02002997 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002998 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002999 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003000 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003001 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3002
Willy Tarreau93893792009-07-23 13:19:11 +02003003 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3007 goto out;
3008
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3010 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3011 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3012 else {
3013 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
3017 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003018 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003019 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003020
3021 if (curproxy == &defproxy) {
3022 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3023 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003026 }
3027
William Lallemanddf1425a2015-04-28 20:17:49 +02003028 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3029 goto out;
3030
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003031 if (!*args[1]) {
3032 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003036 }
3037
3038 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003039 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003040 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003041
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003042 if (curproxy->uuid <= 0) {
3043 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003044 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003047 }
3048
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003049 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3050 if (node) {
3051 struct proxy *target = container_of(node, struct proxy, conf.id);
3052 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3053 file, linenum, proxy_type_str(curproxy), curproxy->id,
3054 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003059 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003060 else if (!strcmp(args[0], "description")) {
3061 int i, len=0;
3062 char *d;
3063
Cyril Bonté99ed3272010-01-24 23:29:44 +01003064 if (curproxy == &defproxy) {
3065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3066 file, linenum, args[0]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
3070
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003071 if (!*args[1]) {
3072 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3073 file, linenum, args[0]);
3074 return -1;
3075 }
3076
Willy Tarreau348acfe2014-04-14 15:00:39 +02003077 for (i = 1; *args[i]; i++)
3078 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003079
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003080 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003081 curproxy->desc = d;
3082
Willy Tarreau348acfe2014-04-14 15:00:39 +02003083 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3084 for (i = 2; *args[i]; i++)
3085 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003086
3087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003089 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 curproxy->state = PR_STSTOPPED;
3092 }
3093 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003094 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 curproxy->state = PR_STNEW;
3097 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003098 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3099 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003100 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003101
3102 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003103 unsigned int low, high;
3104
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003105 if (strcmp(args[cur_arg], "all") == 0) {
3106 set = 0;
3107 break;
3108 }
3109 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003110 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003111 }
3112 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003113 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003114 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003115 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003116 char *dash = strchr(args[cur_arg], '-');
3117
3118 low = high = str2uic(args[cur_arg]);
3119 if (dash)
3120 high = str2uic(dash + 1);
3121
3122 if (high < low) {
3123 unsigned int swap = low;
3124 low = high;
3125 high = swap;
3126 }
3127
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003128 if (low < 1 || high > LONGBITS) {
3129 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3130 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003133 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003134 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003135 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003136 }
3137 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003138 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3139 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003142 }
3143 cur_arg++;
3144 }
3145 curproxy->bind_proc = set;
3146 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003147 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003148 if (curproxy == &defproxy) {
3149 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003152 }
3153
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003154 err = invalid_char(args[1]);
3155 if (err) {
3156 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3157 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003158 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003159 }
3160
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003161 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003162 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3163 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003166 }
3167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3169 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170
Willy Tarreau977b8e42006-12-29 14:19:17 +01003171 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003173
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 if (*(args[1]) == 0) {
3175 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3176 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003180
Willy Tarreau67402132012-05-31 20:40:20 +02003181 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003182 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003183 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003184 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 curproxy->cookie_name = strdup(args[1]);
3186 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003187
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 cur_arg = 2;
3189 while (*(args[cur_arg])) {
3190 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003191 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 }
3193 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003194 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003197 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003200 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003203 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003205 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003206 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003209 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003211 else if (!strcmp(args[cur_arg], "httponly")) {
3212 curproxy->ck_opts |= PR_CK_HTTPONLY;
3213 }
3214 else if (!strcmp(args[cur_arg], "secure")) {
3215 curproxy->ck_opts |= PR_CK_SECURE;
3216 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003217 else if (!strcmp(args[cur_arg], "domain")) {
3218 if (!*args[cur_arg + 1]) {
3219 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3220 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003223 }
3224
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003225 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003226 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003227 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3228 " dots nor does not start with a dot."
3229 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003230 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003231 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003232 }
3233
3234 err = invalid_domainchar(args[cur_arg + 1]);
3235 if (err) {
3236 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3237 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003240 }
3241
Willy Tarreau68a897b2009-12-03 23:28:34 +01003242 if (!curproxy->cookie_domain) {
3243 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3244 } else {
3245 /* one domain was already specified, add another one by
3246 * building the string which will be returned along with
3247 * the cookie.
3248 */
3249 char *new_ptr;
3250 int new_len = strlen(curproxy->cookie_domain) +
3251 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3252 new_ptr = malloc(new_len);
3253 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3254 free(curproxy->cookie_domain);
3255 curproxy->cookie_domain = new_ptr;
3256 }
Willy Tarreau31936852010-10-06 16:59:56 +02003257 cur_arg++;
3258 }
3259 else if (!strcmp(args[cur_arg], "maxidle")) {
3260 unsigned int maxidle;
3261 const char *res;
3262
3263 if (!*args[cur_arg + 1]) {
3264 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3265 file, linenum, args[cur_arg]);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
3269
3270 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3271 if (res) {
3272 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3273 file, linenum, *res, args[cur_arg]);
3274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
3276 }
3277 curproxy->cookie_maxidle = maxidle;
3278 cur_arg++;
3279 }
3280 else if (!strcmp(args[cur_arg], "maxlife")) {
3281 unsigned int maxlife;
3282 const char *res;
3283
3284 if (!*args[cur_arg + 1]) {
3285 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3286 file, linenum, args[cur_arg]);
3287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
3289 }
3290
3291 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3292 if (res) {
3293 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3294 file, linenum, *res, args[cur_arg]);
3295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
3297 }
3298 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003299 cur_arg++;
3300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003302 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 }
3307 cur_arg++;
3308 }
Willy Tarreau67402132012-05-31 20:40:20 +02003309 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3311 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 }
3314
Willy Tarreau67402132012-05-31 20:40:20 +02003315 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3317 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003320
Willy Tarreau67402132012-05-31 20:40:20 +02003321 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003322 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3323 file, linenum);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003327 else if (!strcmp(args[0], "email-alert")) {
3328 if (*(args[1]) == 0) {
3329 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3330 file, linenum, args[0]);
3331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
3333 }
3334
3335 if (!strcmp(args[1], "from")) {
3336 if (*(args[1]) == 0) {
3337 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3338 file, linenum, args[1]);
3339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
3341 }
3342 free(curproxy->email_alert.from);
3343 curproxy->email_alert.from = strdup(args[2]);
3344 }
3345 else if (!strcmp(args[1], "mailers")) {
3346 if (*(args[1]) == 0) {
3347 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3348 file, linenum, args[1]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352 free(curproxy->email_alert.mailers.name);
3353 curproxy->email_alert.mailers.name = strdup(args[2]);
3354 }
3355 else if (!strcmp(args[1], "myhostname")) {
3356 if (*(args[1]) == 0) {
3357 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3358 file, linenum, args[1]);
3359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
3361 }
3362 free(curproxy->email_alert.myhostname);
3363 curproxy->email_alert.myhostname = strdup(args[2]);
3364 }
Simon Horman64e34162015-02-06 11:11:57 +09003365 else if (!strcmp(args[1], "level")) {
3366 curproxy->email_alert.level = get_log_level(args[2]);
3367 if (curproxy->email_alert.level < 0) {
3368 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3369 file, linenum, args[1], args[2]);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
3372 }
3373 }
Simon Horman9dc49962015-01-30 11:22:59 +09003374 else if (!strcmp(args[1], "to")) {
3375 if (*(args[1]) == 0) {
3376 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3377 file, linenum, args[1]);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
3381 free(curproxy->email_alert.to);
3382 curproxy->email_alert.to = strdup(args[2]);
3383 }
3384 else {
3385 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3386 file, linenum, args[1]);
3387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
3389 }
Simon Horman64e34162015-02-06 11:11:57 +09003390 /* Indicate that the email_alert is at least partially configured */
3391 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003392 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003393 else if (!strcmp(args[0], "external-check")) {
3394 if (*(args[1]) == 0) {
3395 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3396 file, linenum, args[0]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400
3401 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003402 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003403 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003404 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003405 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3406 file, linenum, args[1]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
3410 free(curproxy->check_command);
3411 curproxy->check_command = strdup(args[2]);
3412 }
3413 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003414 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003415 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003416 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003417 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3418 file, linenum, args[1]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422 free(curproxy->check_path);
3423 curproxy->check_path = strdup(args[2]);
3424 }
3425 else {
3426 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3427 file, linenum, args[1]);
3428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
3430 }
3431 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003432 else if (!strcmp(args[0], "persist")) { /* persist */
3433 if (*(args[1]) == 0) {
3434 Alert("parsing [%s:%d] : missing persist method.\n",
3435 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003438 }
3439
3440 if (!strncmp(args[1], "rdp-cookie", 10)) {
3441 curproxy->options2 |= PR_O2_RDPC_PRST;
3442
Emeric Brunb982a3d2010-01-04 15:45:53 +01003443 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003444 const char *beg, *end;
3445
3446 beg = args[1] + 11;
3447 end = strchr(beg, ')');
3448
William Lallemanddf1425a2015-04-28 20:17:49 +02003449 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3450 goto out;
3451
Emeric Brun647caf12009-06-30 17:57:00 +02003452 if (!end || end == beg) {
3453 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3454 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003457 }
3458
3459 free(curproxy->rdp_cookie_name);
3460 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3461 curproxy->rdp_cookie_len = end-beg;
3462 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003463 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003464 free(curproxy->rdp_cookie_name);
3465 curproxy->rdp_cookie_name = strdup("msts");
3466 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3467 }
3468 else { /* syntax */
3469 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3470 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003473 }
3474 }
3475 else {
3476 Alert("parsing [%s:%d] : unknown persist method.\n",
3477 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003480 }
3481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003483 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003487 else if (!strcmp(args[0], "load-server-state-from-file")) {
3488 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3489 err_code |= ERR_WARN;
3490 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3491 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3492 }
3493 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3494 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3495 }
3496 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3497 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3498 }
3499 else {
3500 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3501 file, linenum, args[0], args[1]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
3505 }
3506 else if (!strcmp(args[0], "server-state-file-name")) {
3507 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3508 err_code |= ERR_WARN;
3509 if (*(args[1]) == 0) {
3510 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3511 file, linenum, args[0]);
3512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
3514 }
3515 else if (!strcmp(args[1], "use-backend-name"))
3516 curproxy->server_state_file_name = strdup(curproxy->id);
3517 else
3518 curproxy->server_state_file_name = strdup(args[1]);
3519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003521 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003523
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003525 if (curproxy == &defproxy) {
3526 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
3529 }
3530
William Lallemand1a748ae2015-05-19 16:37:23 +02003531 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3532 goto out;
3533
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 if (*(args[4]) == 0) {
3535 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3536 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003540 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 curproxy->capture_name = strdup(args[2]);
3542 curproxy->capture_namelen = strlen(curproxy->capture_name);
3543 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 curproxy->to_log |= LW_COOKIE;
3545 }
3546 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3547 struct cap_hdr *hdr;
3548
3549 if (curproxy == &defproxy) {
3550 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 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }
3554
William Lallemand1a748ae2015-05-19 16:37:23 +02003555 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3556 goto out;
3557
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3559 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3560 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 }
3564
Vincent Bernat02779b62016-04-03 13:48:43 +02003565 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 hdr->next = curproxy->req_cap;
3567 hdr->name = strdup(args[3]);
3568 hdr->namelen = strlen(args[3]);
3569 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003570 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 hdr->index = curproxy->nb_req_cap++;
3572 curproxy->req_cap = hdr;
3573 curproxy->to_log |= LW_REQHDR;
3574 }
3575 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3576 struct cap_hdr *hdr;
3577
3578 if (curproxy == &defproxy) {
3579 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 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
3583
William Lallemand1a748ae2015-05-19 16:37:23 +02003584 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3585 goto out;
3586
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3588 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3589 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003593 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 hdr->next = curproxy->rsp_cap;
3595 hdr->name = strdup(args[3]);
3596 hdr->namelen = strlen(args[3]);
3597 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003598 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 hdr->index = curproxy->nb_rsp_cap++;
3600 curproxy->rsp_cap = hdr;
3601 curproxy->to_log |= LW_RSPHDR;
3602 }
3603 else {
3604 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3605 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
3609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613
William Lallemanddf1425a2015-04-28 20:17:49 +02003614 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3615 goto out;
3616
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 if (*(args[1]) == 0) {
3618 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
3623 curproxy->conn_retries = atol(args[1]);
3624 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003625 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003626 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003627
3628 if (curproxy == &defproxy) {
3629 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
3632 }
3633
Willy Tarreau20b0de52012-12-24 15:45:22 +01003634 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003635 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003636 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3637 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3638 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3639 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003640 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 +01003641 file, linenum, args[0]);
3642 err_code |= ERR_WARN;
3643 }
3644
Willy Tarreauff011f22011-01-06 17:51:27 +01003645 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003646
Willy Tarreauff011f22011-01-06 17:51:27 +01003647 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003648 err_code |= ERR_ALERT | ERR_ABORT;
3649 goto out;
3650 }
3651
Willy Tarreau5002f572014-04-23 01:32:02 +02003652 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003653 err_code |= warnif_cond_conflicts(rule->cond,
3654 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3655 file, linenum);
3656
Willy Tarreauff011f22011-01-06 17:51:27 +01003657 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003658 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003659 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003660 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003661
3662 if (curproxy == &defproxy) {
3663 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
3666 }
3667
3668 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003669 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003670 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3671 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003672 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3673 file, linenum, args[0]);
3674 err_code |= ERR_WARN;
3675 }
3676
3677 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3678
3679 if (!rule) {
3680 err_code |= ERR_ALERT | ERR_ABORT;
3681 goto out;
3682 }
3683
3684 err_code |= warnif_cond_conflicts(rule->cond,
3685 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3686 file, linenum);
3687
3688 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3689 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003690 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3691 /* set the header name and length into the proxy structure */
3692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3693 err_code |= ERR_WARN;
3694
3695 if (!*args[1]) {
3696 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3697 file, linenum, args[0]);
3698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
3700 }
3701
3702 /* set the desired header name */
3703 free(curproxy->server_id_hdr_name);
3704 curproxy->server_id_hdr_name = strdup(args[1]);
3705 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3706 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003707 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003708 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003709
Willy Tarreaub099aca2008-10-12 17:26:37 +02003710 if (curproxy == &defproxy) {
3711 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003714 }
3715
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003716 /* emulate "block" using "http-request block". Since these rules are supposed to
3717 * be processed before all http-request rules, we put them into their own list
3718 * and will insert them at the end.
3719 */
3720 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3721 if (!rule) {
3722 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003723 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003724 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003725 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3726 err_code |= warnif_cond_conflicts(rule->cond,
3727 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3728 file, linenum);
3729 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003730
3731 if (!already_warned(WARN_BLOCK_DEPRECATED))
3732 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]);
3733
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003734 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003735 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003736 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003737
Cyril Bonté99ed3272010-01-24 23:29:44 +01003738 if (curproxy == &defproxy) {
3739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743
Willy Tarreaube4653b2015-05-28 15:26:58 +02003744 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003745 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3746 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003749 }
3750
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003751 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003752 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003753 err_code |= warnif_cond_conflicts(rule->cond,
3754 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3755 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003756 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003757 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003758 struct switching_rule *rule;
3759
Willy Tarreaub099aca2008-10-12 17:26:37 +02003760 if (curproxy == &defproxy) {
3761 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003764 }
3765
Willy Tarreau55ea7572007-06-17 19:56:27 +02003766 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003768
3769 if (*(args[1]) == 0) {
3770 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003773 }
3774
Willy Tarreauf51658d2014-04-23 01:21:56 +02003775 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3776 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3777 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3778 file, linenum, errmsg);
3779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
3781 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003782
Willy Tarreauf51658d2014-04-23 01:21:56 +02003783 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003784 }
3785
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003786 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003787 if (!rule) {
3788 Alert("Out of memory error.\n");
3789 goto out;
3790 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003791 rule->cond = cond;
3792 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003793 rule->line = linenum;
3794 rule->file = strdup(file);
3795 if (!rule->file) {
3796 Alert("Out of memory error.\n");
3797 goto out;
3798 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003799 LIST_INIT(&rule->list);
3800 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3801 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003802 else if (strcmp(args[0], "use-server") == 0) {
3803 struct server_rule *rule;
3804
3805 if (curproxy == &defproxy) {
3806 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
3810
3811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3812 err_code |= ERR_WARN;
3813
3814 if (*(args[1]) == 0) {
3815 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
3818 }
3819
3820 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3821 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3822 file, linenum, args[0]);
3823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
3825 }
3826
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003827 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3828 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3829 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
3832 }
3833
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003834 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003835
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003836 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003837 rule->cond = cond;
3838 rule->srv.name = strdup(args[1]);
3839 LIST_INIT(&rule->list);
3840 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3841 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3842 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003843 else if ((!strcmp(args[0], "force-persist")) ||
3844 (!strcmp(args[0], "ignore-persist"))) {
3845 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003846
3847 if (curproxy == &defproxy) {
3848 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852
3853 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3854 err_code |= ERR_WARN;
3855
Willy Tarreauef6494c2010-01-28 17:12:36 +01003856 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003857 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3858 file, linenum, args[0]);
3859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
3861 }
3862
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003863 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3864 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3865 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
3869
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003870 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3871 * where force-persist is applied.
3872 */
3873 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003874
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003875 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003876 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003877 if (!strcmp(args[0], "force-persist")) {
3878 rule->type = PERSIST_TYPE_FORCE;
3879 } else {
3880 rule->type = PERSIST_TYPE_IGNORE;
3881 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003882 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003883 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003884 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003885 else if (!strcmp(args[0], "stick-table")) {
3886 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003887 struct proxy *other;
3888
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003889 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003890 if (other) {
3891 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3892 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003896
Emeric Brun32da3c42010-09-23 18:39:19 +02003897 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003898 curproxy->table.type = (unsigned int)-1;
3899 while (*args[myidx]) {
3900 const char *err;
3901
3902 if (strcmp(args[myidx], "size") == 0) {
3903 myidx++;
3904 if (!*(args[myidx])) {
3905 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3906 file, linenum, args[myidx-1]);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
3910 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3911 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3912 file, linenum, *err, args[myidx-1]);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003916 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003917 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003918 else if (strcmp(args[myidx], "peers") == 0) {
3919 myidx++;
Godbach50523162013-12-11 19:48:57 +08003920 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003921 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3922 file, linenum, args[myidx-1]);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
Godbach50523162013-12-11 19:48:57 +08003925 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003926 curproxy->table.peers.name = strdup(args[myidx++]);
3927 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003928 else if (strcmp(args[myidx], "expire") == 0) {
3929 myidx++;
3930 if (!*(args[myidx])) {
3931 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3932 file, linenum, args[myidx-1]);
3933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
3935 }
3936 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3937 if (err) {
3938 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3939 file, linenum, *err, args[myidx-1]);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003943 if (val > INT_MAX) {
3944 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3945 file, linenum, val);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003949 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003950 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003951 }
3952 else if (strcmp(args[myidx], "nopurge") == 0) {
3953 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003954 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003955 }
3956 else if (strcmp(args[myidx], "type") == 0) {
3957 myidx++;
3958 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3959 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3960 file, linenum, args[myidx]);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003964 /* myidx already points to next arg */
3965 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003966 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003967 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003968 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003969
3970 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003971 nw = args[myidx];
3972 while (*nw) {
3973 /* the "store" keyword supports a comma-separated list */
3974 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003975 sa = NULL; /* store arg */
3976 while (*nw && *nw != ',') {
3977 if (*nw == '(') {
3978 *nw = 0;
3979 sa = ++nw;
3980 while (*nw != ')') {
3981 if (!*nw) {
3982 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3983 file, linenum, args[0], cw);
3984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
3986 }
3987 nw++;
3988 }
3989 *nw = '\0';
3990 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003991 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003992 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003993 if (*nw)
3994 *nw++ = '\0';
3995 type = stktable_get_data_type(cw);
3996 if (type < 0) {
3997 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3998 file, linenum, args[0], cw);
3999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
Willy Tarreauac782882010-06-20 10:41:54 +02004002
4003 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4004 switch (err) {
4005 case PE_NONE: break;
4006 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004007 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4008 file, linenum, args[0], cw);
4009 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004010 break;
4011
4012 case PE_ARG_MISSING:
4013 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4014 file, linenum, args[0], cw);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017
4018 case PE_ARG_NOT_USED:
4019 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4020 file, linenum, args[0], cw);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023
4024 default:
4025 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4026 file, linenum, args[0], cw);
4027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004029 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004030 }
4031 myidx++;
4032 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004033 else {
4034 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4035 file, linenum, args[myidx]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004038 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004039 }
4040
4041 if (!curproxy->table.size) {
4042 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4043 file, linenum);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047
4048 if (curproxy->table.type == (unsigned int)-1) {
4049 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4050 file, linenum);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054 }
4055 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004056 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004057 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004058 int myidx = 0;
4059 const char *name = NULL;
4060 int flags;
4061
4062 if (curproxy == &defproxy) {
4063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
4066 }
4067
4068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4069 err_code |= ERR_WARN;
4070 goto out;
4071 }
4072
4073 myidx++;
4074 if ((strcmp(args[myidx], "store") == 0) ||
4075 (strcmp(args[myidx], "store-request") == 0)) {
4076 myidx++;
4077 flags = STK_IS_STORE;
4078 }
4079 else if (strcmp(args[myidx], "store-response") == 0) {
4080 myidx++;
4081 flags = STK_IS_STORE | STK_ON_RSP;
4082 }
4083 else if (strcmp(args[myidx], "match") == 0) {
4084 myidx++;
4085 flags = STK_IS_MATCH;
4086 }
4087 else if (strcmp(args[myidx], "on") == 0) {
4088 myidx++;
4089 flags = STK_IS_MATCH | STK_IS_STORE;
4090 }
4091 else {
4092 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096
4097 if (*(args[myidx]) == 0) {
4098 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
4102
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004103 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004104 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004105 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004106 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110
4111 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004112 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4113 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4114 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004115 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004116 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004117 goto out;
4118 }
4119 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004120 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4121 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4122 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004123 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004124 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 goto out;
4126 }
4127 }
4128
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004129 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004130 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004131
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 if (strcmp(args[myidx], "table") == 0) {
4133 myidx++;
4134 name = args[myidx++];
4135 }
4136
Willy Tarreauef6494c2010-01-28 17:12:36 +01004137 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004138 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4139 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4140 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004141 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004142 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004143 goto out;
4144 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004145 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004146 else if (*(args[myidx])) {
4147 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4148 file, linenum, args[0], args[myidx]);
4149 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004150 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004151 goto out;
4152 }
Emeric Brun97679e72010-09-23 17:56:44 +02004153 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004154 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004155 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004156 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004157
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004158 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004159 rule->cond = cond;
4160 rule->expr = expr;
4161 rule->flags = flags;
4162 rule->table.name = name ? strdup(name) : NULL;
4163 LIST_INIT(&rule->list);
4164 if (flags & STK_ON_RSP)
4165 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4166 else
4167 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 else if (!strcmp(args[0], "stats")) {
4170 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4171 curproxy->uri_auth = NULL; /* we must detach from the default config */
4172
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004173 if (!*args[1]) {
4174 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004175 } else if (!strcmp(args[1], "admin")) {
4176 struct stats_admin_rule *rule;
4177
4178 if (curproxy == &defproxy) {
4179 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
4182 }
4183
4184 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4185 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4186 err_code |= ERR_ALERT | ERR_ABORT;
4187 goto out;
4188 }
4189
4190 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4191 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4192 file, linenum, args[0], args[1]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004196 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4197 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4198 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
4202
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004203 err_code |= warnif_cond_conflicts(cond,
4204 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4205 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004206
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004207 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004208 rule->cond = cond;
4209 LIST_INIT(&rule->list);
4210 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 } else if (!strcmp(args[1], "uri")) {
4212 if (*(args[2]) == 0) {
4213 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_ABORT;
4219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 }
4221 } else if (!strcmp(args[1], "realm")) {
4222 if (*(args[2]) == 0) {
4223 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4227 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_ABORT;
4229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004231 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004232 unsigned interval;
4233
4234 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4235 if (err) {
4236 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4237 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004240 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_ABORT;
4243 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004244 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004245 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004246 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004247
4248 if (curproxy == &defproxy) {
4249 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
4252 }
4253
4254 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4255 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4256 err_code |= ERR_ALERT | ERR_ABORT;
4257 goto out;
4258 }
4259
Willy Tarreauff011f22011-01-06 17:51:27 +01004260 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004261 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004262 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4263 file, linenum, args[0]);
4264 err_code |= ERR_WARN;
4265 }
4266
Willy Tarreauff011f22011-01-06 17:51:27 +01004267 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004268
Willy Tarreauff011f22011-01-06 17:51:27 +01004269 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004270 err_code |= ERR_ALERT | ERR_ABORT;
4271 goto out;
4272 }
4273
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004274 err_code |= warnif_cond_conflicts(rule->cond,
4275 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4276 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004277 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004278
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 } else if (!strcmp(args[1], "auth")) {
4280 if (*(args[2]) == 0) {
4281 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_ABORT;
4287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 }
4289 } else if (!strcmp(args[1], "scope")) {
4290 if (*(args[2]) == 0) {
4291 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_ABORT;
4297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 }
4299 } else if (!strcmp(args[1], "enable")) {
4300 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_ABORT;
4303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004305 } else if (!strcmp(args[1], "hide-version")) {
4306 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4307 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_ABORT;
4309 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004310 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004311 } else if (!strcmp(args[1], "show-legends")) {
4312 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4313 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4314 err_code |= ERR_ALERT | ERR_ABORT;
4315 goto out;
4316 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004317 } else if (!strcmp(args[1], "show-node")) {
4318
4319 if (*args[2]) {
4320 int i;
4321 char c;
4322
4323 for (i=0; args[2][i]; i++) {
4324 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004325 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4326 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004327 break;
4328 }
4329
4330 if (!i || args[2][i]) {
4331 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4332 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4333 file, linenum, args[0], args[1]);
4334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
4336 }
4337 }
4338
4339 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4340 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4341 err_code |= ERR_ALERT | ERR_ABORT;
4342 goto out;
4343 }
4344 } else if (!strcmp(args[1], "show-desc")) {
4345 char *desc = NULL;
4346
4347 if (*args[2]) {
4348 int i, len=0;
4349 char *d;
4350
Willy Tarreau348acfe2014-04-14 15:00:39 +02004351 for (i = 2; *args[i]; i++)
4352 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004353
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004354 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004355
Willy Tarreau348acfe2014-04-14 15:00:39 +02004356 d += snprintf(d, desc + len - d, "%s", args[2]);
4357 for (i = 3; *args[i]; i++)
4358 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004359 }
4360
4361 if (!*args[2] && !global.desc)
4362 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4363 file, linenum, args[1]);
4364 else {
4365 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4366 free(desc);
4367 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4368 err_code |= ERR_ALERT | ERR_ABORT;
4369 goto out;
4370 }
4371 free(desc);
4372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004374stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004375 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 +01004376 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004379 }
4380 }
4381 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004382 int optnum;
4383
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004384 if (*(args[1]) == '\0') {
4385 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004390
4391 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4392 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004393 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4394 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4395 file, linenum, cfg_opts[optnum].name);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004399 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4400 goto out;
4401
Willy Tarreau93893792009-07-23 13:19:11 +02004402 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4403 err_code |= ERR_WARN;
4404 goto out;
4405 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004406
Willy Tarreau3842f002009-06-14 11:39:52 +02004407 curproxy->no_options &= ~cfg_opts[optnum].val;
4408 curproxy->options &= ~cfg_opts[optnum].val;
4409
4410 switch (kwm) {
4411 case KWM_STD:
4412 curproxy->options |= cfg_opts[optnum].val;
4413 break;
4414 case KWM_NO:
4415 curproxy->no_options |= cfg_opts[optnum].val;
4416 break;
4417 case KWM_DEF: /* already cleared */
4418 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004419 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004420
Willy Tarreau93893792009-07-23 13:19:11 +02004421 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004422 }
4423 }
4424
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004425 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4426 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004427 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4428 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4429 file, linenum, cfg_opts2[optnum].name);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004433 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4434 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004435 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4436 err_code |= ERR_WARN;
4437 goto out;
4438 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004439
Willy Tarreau3842f002009-06-14 11:39:52 +02004440 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4441 curproxy->options2 &= ~cfg_opts2[optnum].val;
4442
4443 switch (kwm) {
4444 case KWM_STD:
4445 curproxy->options2 |= cfg_opts2[optnum].val;
4446 break;
4447 case KWM_NO:
4448 curproxy->no_options2 |= cfg_opts2[optnum].val;
4449 break;
4450 case KWM_DEF: /* already cleared */
4451 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004452 }
Willy Tarreau93893792009-07-23 13:19:11 +02004453 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004454 }
4455 }
4456
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004457 /* HTTP options override each other. They can be cancelled using
4458 * "no option xxx" which only switches to default mode if the mode
4459 * was this one (useful for cancelling options set in defaults
4460 * sections).
4461 */
4462 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004463 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4464 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004465 if (kwm == KWM_STD) {
4466 curproxy->options &= ~PR_O_HTTP_MODE;
4467 curproxy->options |= PR_O_HTTP_PCL;
4468 goto out;
4469 }
4470 else if (kwm == KWM_NO) {
4471 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4472 curproxy->options &= ~PR_O_HTTP_MODE;
4473 goto out;
4474 }
4475 }
4476 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004477 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4478 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004479 if (kwm == KWM_STD) {
4480 curproxy->options &= ~PR_O_HTTP_MODE;
4481 curproxy->options |= PR_O_HTTP_FCL;
4482 goto out;
4483 }
4484 else if (kwm == KWM_NO) {
4485 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4486 curproxy->options &= ~PR_O_HTTP_MODE;
4487 goto out;
4488 }
4489 }
4490 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004491 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4492 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004493 if (kwm == KWM_STD) {
4494 curproxy->options &= ~PR_O_HTTP_MODE;
4495 curproxy->options |= PR_O_HTTP_SCL;
4496 goto out;
4497 }
4498 else if (kwm == KWM_NO) {
4499 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4500 curproxy->options &= ~PR_O_HTTP_MODE;
4501 goto out;
4502 }
4503 }
4504 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004505 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4506 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004507 if (kwm == KWM_STD) {
4508 curproxy->options &= ~PR_O_HTTP_MODE;
4509 curproxy->options |= PR_O_HTTP_KAL;
4510 goto out;
4511 }
4512 else if (kwm == KWM_NO) {
4513 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4514 curproxy->options &= ~PR_O_HTTP_MODE;
4515 goto out;
4516 }
4517 }
4518 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004519 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4520 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004521 if (kwm == KWM_STD) {
4522 curproxy->options &= ~PR_O_HTTP_MODE;
4523 curproxy->options |= PR_O_HTTP_TUN;
4524 goto out;
4525 }
4526 else if (kwm == KWM_NO) {
4527 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4528 curproxy->options &= ~PR_O_HTTP_MODE;
4529 goto out;
4530 }
4531 }
4532
Joseph Lynch726ab712015-05-11 23:25:34 -07004533 /* Redispatch can take an integer argument that control when the
4534 * resispatch occurs. All values are relative to the retries option.
4535 * This can be cancelled using "no option xxx".
4536 */
4537 if (strcmp(args[1], "redispatch") == 0) {
4538 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4539 err_code |= ERR_WARN;
4540 goto out;
4541 }
4542
4543 curproxy->no_options &= ~PR_O_REDISP;
4544 curproxy->options &= ~PR_O_REDISP;
4545
4546 switch (kwm) {
4547 case KWM_STD:
4548 curproxy->options |= PR_O_REDISP;
4549 curproxy->redispatch_after = -1;
4550 if(*args[2]) {
4551 curproxy->redispatch_after = atol(args[2]);
4552 }
4553 break;
4554 case KWM_NO:
4555 curproxy->no_options |= PR_O_REDISP;
4556 curproxy->redispatch_after = 0;
4557 break;
4558 case KWM_DEF: /* already cleared */
4559 break;
4560 }
4561 goto out;
4562 }
4563
Willy Tarreau3842f002009-06-14 11:39:52 +02004564 if (kwm != KWM_STD) {
4565 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004566 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004569 }
4570
Emeric Brun3a058f32009-06-30 18:26:00 +02004571 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004572 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004574 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004575 if (*(args[2]) != '\0') {
4576 if (!strcmp(args[2], "clf")) {
4577 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004578 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004579 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004580 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004583 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004584 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4585 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004586 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004587 if (curproxy->conf.logformat_string != default_http_log_format &&
4588 curproxy->conf.logformat_string != default_tcp_log_format &&
4589 curproxy->conf.logformat_string != clf_http_log_format)
4590 free(curproxy->conf.logformat_string);
4591 curproxy->conf.logformat_string = logformat;
4592
4593 free(curproxy->conf.lfs_file);
4594 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4595 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004596 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004597 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004599 if (curproxy->conf.logformat_string != default_http_log_format &&
4600 curproxy->conf.logformat_string != default_tcp_log_format &&
4601 curproxy->conf.logformat_string != clf_http_log_format)
4602 free(curproxy->conf.logformat_string);
4603 curproxy->conf.logformat_string = default_tcp_log_format;
4604
4605 free(curproxy->conf.lfs_file);
4606 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4607 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004608
4609 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4610 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004613 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004614 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004616
William Lallemanddf1425a2015-04-28 20:17:49 +02004617 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4618 goto out;
4619
Willy Tarreau13943ab2006-12-31 00:24:10 +01004620 if (curproxy->cap & PR_CAP_FE)
4621 curproxy->options |= PR_O_TCP_CLI_KA;
4622 if (curproxy->cap & PR_CAP_BE)
4623 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624 }
4625 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004626 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004627 err_code |= ERR_WARN;
4628
Willy Tarreaubaaee002006-06-26 02:48:02 +02004629 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004630 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004631 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004632 curproxy->options2 &= ~PR_O2_CHK_ANY;
4633 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 if (!*args[2]) { /* no argument */
4635 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4636 curproxy->check_len = strlen(DEF_CHECK_REQ);
4637 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004638 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004639 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004641 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004643 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004644 if (*args[4])
4645 reqlen += strlen(args[4]);
4646 else
4647 reqlen += strlen("HTTP/1.0");
4648
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004649 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004651 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004653 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4654 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004655 }
4656 else if (!strcmp(args[1], "ssl-hello-chk")) {
4657 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004660
Willy Tarreaua534fea2008-08-03 12:19:50 +02004661 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004662 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004663 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004664 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004665
4666 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 }
Willy Tarreau23677902007-05-08 23:50:35 +02004669 else if (!strcmp(args[1], "smtpchk")) {
4670 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004671 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004672 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004673 curproxy->options2 &= ~PR_O2_CHK_ANY;
4674 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004675
4676 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4677 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4678 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4679 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4680 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4681 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004682 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004683 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4684 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4685 } else {
4686 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4687 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4688 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4689 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4690 }
4691 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004692 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4693 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004694 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004695 else if (!strcmp(args[1], "pgsql-check")) {
4696 /* use PostgreSQL request to check servers' health */
4697 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4698 err_code |= ERR_WARN;
4699
4700 free(curproxy->check_req);
4701 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004702 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004703 curproxy->options2 |= PR_O2_PGSQL_CHK;
4704
4705 if (*(args[2])) {
4706 int cur_arg = 2;
4707
4708 while (*(args[cur_arg])) {
4709 if (strcmp(args[cur_arg], "user") == 0) {
4710 char * packet;
4711 uint32_t packet_len;
4712 uint32_t pv;
4713
4714 /* suboption header - needs additional argument for it */
4715 if (*(args[cur_arg+1]) == 0) {
4716 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4717 file, linenum, args[0], args[1], args[cur_arg]);
4718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720 }
4721
4722 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4723 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4724 pv = htonl(0x30000); /* protocol version 3.0 */
4725
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004726 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004727
4728 memcpy(packet + 4, &pv, 4);
4729
4730 /* copy "user" */
4731 memcpy(packet + 8, "user", 4);
4732
4733 /* copy username */
4734 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4735
4736 free(curproxy->check_req);
4737 curproxy->check_req = packet;
4738 curproxy->check_len = packet_len;
4739
4740 packet_len = htonl(packet_len);
4741 memcpy(packet, &packet_len, 4);
4742 cur_arg += 2;
4743 } else {
4744 /* unknown suboption - catchall */
4745 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4746 file, linenum, args[0], args[1]);
4747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
4749 }
4750 } /* end while loop */
4751 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004752 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4753 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004754 }
4755
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004756 else if (!strcmp(args[1], "redis-check")) {
4757 /* use REDIS PING request to check servers' health */
4758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4759 err_code |= ERR_WARN;
4760
4761 free(curproxy->check_req);
4762 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004763 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004764 curproxy->options2 |= PR_O2_REDIS_CHK;
4765
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004766 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004767 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4768 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004769
4770 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4771 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004772 }
4773
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004774 else if (!strcmp(args[1], "mysql-check")) {
4775 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4777 err_code |= ERR_WARN;
4778
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004779 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004780 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004781 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004782 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004783
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004784 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004785 * const char mysql40_client_auth_pkt[] = {
4786 * "\x0e\x00\x00" // packet length
4787 * "\x01" // packet number
4788 * "\x00\x00" // client capabilities
4789 * "\x00\x00\x01" // max packet
4790 * "haproxy\x00" // username (null terminated string)
4791 * "\x00" // filler (always 0x00)
4792 * "\x01\x00\x00" // packet length
4793 * "\x00" // packet number
4794 * "\x01" // COM_QUIT command
4795 * };
4796 */
4797
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004798 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4799 * const char mysql41_client_auth_pkt[] = {
4800 * "\x0e\x00\x00\" // packet length
4801 * "\x01" // packet number
4802 * "\x00\x00\x00\x00" // client capabilities
4803 * "\x00\x00\x00\x01" // max packet
4804 * "\x21" // character set (UTF-8)
4805 * char[23] // All zeroes
4806 * "haproxy\x00" // username (null terminated string)
4807 * "\x00" // filler (always 0x00)
4808 * "\x01\x00\x00" // packet length
4809 * "\x00" // packet number
4810 * "\x01" // COM_QUIT command
4811 * };
4812 */
4813
4814
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004815 if (*(args[2])) {
4816 int cur_arg = 2;
4817
4818 while (*(args[cur_arg])) {
4819 if (strcmp(args[cur_arg], "user") == 0) {
4820 char *mysqluser;
4821 int packetlen, reqlen, userlen;
4822
4823 /* suboption header - needs additional argument for it */
4824 if (*(args[cur_arg+1]) == 0) {
4825 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4826 file, linenum, args[0], args[1], args[cur_arg]);
4827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
4829 }
4830 mysqluser = args[cur_arg + 1];
4831 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004832
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004833 if (*(args[cur_arg+2])) {
4834 if (!strcmp(args[cur_arg+2], "post-41")) {
4835 packetlen = userlen + 7 + 27;
4836 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004837
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004838 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004839 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004840 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004841
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004842 snprintf(curproxy->check_req, 4, "%c%c%c",
4843 ((unsigned char) packetlen & 0xff),
4844 ((unsigned char) (packetlen >> 8) & 0xff),
4845 ((unsigned char) (packetlen >> 16) & 0xff));
4846
4847 curproxy->check_req[3] = 1;
4848 curproxy->check_req[5] = 130;
4849 curproxy->check_req[11] = 1;
4850 curproxy->check_req[12] = 33;
4851 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4852 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4853 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4854 cur_arg += 3;
4855 } else {
4856 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
4859 }
4860 } else {
4861 packetlen = userlen + 7;
4862 reqlen = packetlen + 9;
4863
4864 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004865 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004866 curproxy->check_len = reqlen;
4867
4868 snprintf(curproxy->check_req, 4, "%c%c%c",
4869 ((unsigned char) packetlen & 0xff),
4870 ((unsigned char) (packetlen >> 8) & 0xff),
4871 ((unsigned char) (packetlen >> 16) & 0xff));
4872
4873 curproxy->check_req[3] = 1;
4874 curproxy->check_req[5] = 128;
4875 curproxy->check_req[8] = 1;
4876 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4877 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4878 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4879 cur_arg += 2;
4880 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004881 } else {
4882 /* unknown suboption - catchall */
4883 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4884 file, linenum, args[0], args[1]);
4885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
4888 } /* end while loop */
4889 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004890 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004891 else if (!strcmp(args[1], "ldap-check")) {
4892 /* use LDAP request to check servers' health */
4893 free(curproxy->check_req);
4894 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004895 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004896 curproxy->options2 |= PR_O2_LDAP_CHK;
4897
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004898 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004899 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4900 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004901 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4902 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004903 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004904 else if (!strcmp(args[1], "spop-check")) {
4905 if (curproxy == &defproxy) {
4906 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4907 file, linenum, args[0], args[1]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
4911 if (curproxy->cap & PR_CAP_FE) {
4912 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4913 file, linenum, args[0], args[1]);
4914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
4916 }
4917
4918 /* use SPOE request to check servers' health */
4919 free(curproxy->check_req);
4920 curproxy->check_req = NULL;
4921 curproxy->options2 &= ~PR_O2_CHK_ANY;
4922 curproxy->options2 |= PR_O2_SPOP_CHK;
4923
4924 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
4925 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
4928 }
4929 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4930 goto out;
4931 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004932 else if (!strcmp(args[1], "tcp-check")) {
4933 /* use raw TCPCHK send/expect to check servers' health */
4934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4935 err_code |= ERR_WARN;
4936
4937 free(curproxy->check_req);
4938 curproxy->check_req = NULL;
4939 curproxy->options2 &= ~PR_O2_CHK_ANY;
4940 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004941 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4942 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004943 }
Simon Horman98637e52014-06-20 12:30:16 +09004944 else if (!strcmp(args[1], "external-check")) {
4945 /* excute an external command to check servers' health */
4946 free(curproxy->check_req);
4947 curproxy->check_req = NULL;
4948 curproxy->options2 &= ~PR_O2_CHK_ANY;
4949 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004950 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4951 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004952 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004953 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004954 int cur_arg;
4955
4956 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4957 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004958 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004959
Willy Tarreau87cf5142011-08-19 22:57:24 +02004960 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004961
4962 free(curproxy->fwdfor_hdr_name);
4963 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4964 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4965
4966 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4967 cur_arg = 2;
4968 while (*(args[cur_arg])) {
4969 if (!strcmp(args[cur_arg], "except")) {
4970 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004971 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004972 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4973 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004976 }
4977 /* flush useless bits */
4978 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004979 cur_arg += 2;
4980 } else if (!strcmp(args[cur_arg], "header")) {
4981 /* suboption header - needs additional argument for it */
4982 if (*(args[cur_arg+1]) == 0) {
4983 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4984 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004987 }
4988 free(curproxy->fwdfor_hdr_name);
4989 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4990 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4991 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004992 } else if (!strcmp(args[cur_arg], "if-none")) {
4993 curproxy->options &= ~PR_O_FF_ALWAYS;
4994 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004995 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004996 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004997 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004998 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005001 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005002 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005003 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005004 else if (!strcmp(args[1], "originalto")) {
5005 int cur_arg;
5006
5007 /* insert x-original-to field, but not for the IP address listed as an except.
5008 * set default options (ie: bitfield, header name, etc)
5009 */
5010
5011 curproxy->options |= PR_O_ORGTO;
5012
5013 free(curproxy->orgto_hdr_name);
5014 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5015 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5016
Willy Tarreau87cf5142011-08-19 22:57:24 +02005017 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005018 cur_arg = 2;
5019 while (*(args[cur_arg])) {
5020 if (!strcmp(args[cur_arg], "except")) {
5021 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005022 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 +02005023 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5024 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005027 }
5028 /* flush useless bits */
5029 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5030 cur_arg += 2;
5031 } else if (!strcmp(args[cur_arg], "header")) {
5032 /* suboption header - needs additional argument for it */
5033 if (*(args[cur_arg+1]) == 0) {
5034 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5035 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005038 }
5039 free(curproxy->orgto_hdr_name);
5040 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5041 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5042 cur_arg += 2;
5043 } else {
5044 /* unknown suboption - catchall */
5045 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5046 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005049 }
5050 } /* end while loop */
5051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 else {
5053 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 }
Willy Tarreau93893792009-07-23 13:19:11 +02005057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005058 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005059 else if (!strcmp(args[0], "default_backend")) {
5060 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005062
5063 if (*(args[1]) == 0) {
5064 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005067 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005068 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005069 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005070
5071 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5072 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005075 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005077
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005078 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5079 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 +01005080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 /* enable reconnections to dispatch */
5083 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005084
5085 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005088 else if (!strcmp(args[0], "http-reuse")) {
5089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5090 err_code |= ERR_WARN;
5091
5092 if (strcmp(args[1], "never") == 0) {
5093 /* enable a graceful server shutdown on an HTTP 404 response */
5094 curproxy->options &= ~PR_O_REUSE_MASK;
5095 curproxy->options |= PR_O_REUSE_NEVR;
5096 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5097 goto out;
5098 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005099 else if (strcmp(args[1], "safe") == 0) {
5100 /* enable a graceful server shutdown on an HTTP 404 response */
5101 curproxy->options &= ~PR_O_REUSE_MASK;
5102 curproxy->options |= PR_O_REUSE_SAFE;
5103 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5104 goto out;
5105 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005106 else if (strcmp(args[1], "aggressive") == 0) {
5107 curproxy->options &= ~PR_O_REUSE_MASK;
5108 curproxy->options |= PR_O_REUSE_AGGR;
5109 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5110 goto out;
5111 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005112 else if (strcmp(args[1], "always") == 0) {
5113 /* enable a graceful server shutdown on an HTTP 404 response */
5114 curproxy->options &= ~PR_O_REUSE_MASK;
5115 curproxy->options |= PR_O_REUSE_ALWS;
5116 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5117 goto out;
5118 }
5119 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005120 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
5123 }
5124 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005125 else if (!strcmp(args[0], "http-check")) {
5126 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005127 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005128
5129 if (strcmp(args[1], "disable-on-404") == 0) {
5130 /* enable a graceful server shutdown on an HTTP 404 response */
5131 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005132 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5133 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005134 }
Willy Tarreauef781042010-01-27 11:53:01 +01005135 else if (strcmp(args[1], "send-state") == 0) {
5136 /* enable emission of the apparent state of a server in HTTP checks */
5137 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005138 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5139 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005140 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005141 else if (strcmp(args[1], "expect") == 0) {
5142 const char *ptr_arg;
5143 int cur_arg;
5144
5145 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5146 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
5149 }
5150
5151 cur_arg = 2;
5152 /* consider exclamation marks, sole or at the beginning of a word */
5153 while (*(ptr_arg = args[cur_arg])) {
5154 while (*ptr_arg == '!') {
5155 curproxy->options2 ^= PR_O2_EXP_INV;
5156 ptr_arg++;
5157 }
5158 if (*ptr_arg)
5159 break;
5160 cur_arg++;
5161 }
5162 /* now ptr_arg points to the beginning of a word past any possible
5163 * exclamation mark, and cur_arg is the argument which holds this word.
5164 */
5165 if (strcmp(ptr_arg, "status") == 0) {
5166 if (!*(args[cur_arg + 1])) {
5167 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5168 file, linenum, args[0], args[1], ptr_arg);
5169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
5171 }
5172 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005173 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005174 curproxy->expect_str = strdup(args[cur_arg + 1]);
5175 }
5176 else if (strcmp(ptr_arg, "string") == 0) {
5177 if (!*(args[cur_arg + 1])) {
5178 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5179 file, linenum, args[0], args[1], ptr_arg);
5180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
5182 }
5183 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005184 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005185 curproxy->expect_str = strdup(args[cur_arg + 1]);
5186 }
5187 else if (strcmp(ptr_arg, "rstatus") == 0) {
5188 if (!*(args[cur_arg + 1])) {
5189 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5190 file, linenum, args[0], args[1], ptr_arg);
5191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
5193 }
5194 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005195 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005196 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005197 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005198 free(curproxy->expect_regex);
5199 curproxy->expect_regex = NULL;
5200 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005201 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005202 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5203 error = NULL;
5204 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5205 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5206 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5207 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
5210 }
5211 }
5212 else if (strcmp(ptr_arg, "rstring") == 0) {
5213 if (!*(args[cur_arg + 1])) {
5214 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5215 file, linenum, args[0], args[1], ptr_arg);
5216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
5218 }
5219 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005220 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005221 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005222 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005223 free(curproxy->expect_regex);
5224 curproxy->expect_regex = NULL;
5225 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005226 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005227 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5228 error = NULL;
5229 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5230 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5231 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5232 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
5235 }
5236 }
5237 else {
5238 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5239 file, linenum, args[0], args[1], ptr_arg);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005244 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005245 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 +02005246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005248 }
5249 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005250 else if (!strcmp(args[0], "tcp-check")) {
5251 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5252 err_code |= ERR_WARN;
5253
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005254 if (strcmp(args[1], "comment") == 0) {
5255 int cur_arg;
5256 struct tcpcheck_rule *tcpcheck;
5257
5258 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005259 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005260 tcpcheck->action = TCPCHK_ACT_COMMENT;
5261
5262 if (!*args[cur_arg + 1]) {
5263 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5264 file, linenum, args[cur_arg]);
5265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
5267 }
5268
5269 tcpcheck->comment = strdup(args[cur_arg + 1]);
5270
5271 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005272 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5273 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005274 }
5275 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005276 const char *ptr_arg;
5277 int cur_arg;
5278 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005279
5280 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005281 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5282 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5283 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5284 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5285 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005286
Willy Tarreau5581c272015-05-13 12:24:53 +02005287 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5288 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5289 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5290 file, linenum);
5291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005293 }
5294
5295 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005296 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005297 tcpcheck->action = TCPCHK_ACT_CONNECT;
5298
5299 /* parsing each parameters to fill up the rule */
5300 while (*(ptr_arg = args[cur_arg])) {
5301 /* tcp port */
5302 if (strcmp(args[cur_arg], "port") == 0) {
5303 if ( (atol(args[cur_arg + 1]) > 65535) ||
5304 (atol(args[cur_arg + 1]) < 1) ){
5305 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5306 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
5310 tcpcheck->port = atol(args[cur_arg + 1]);
5311 cur_arg += 2;
5312 }
5313 /* send proxy protocol */
5314 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5315 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5316 cur_arg++;
5317 }
5318#ifdef USE_OPENSSL
5319 else if (strcmp(args[cur_arg], "ssl") == 0) {
5320 curproxy->options |= PR_O_TCPCHK_SSL;
5321 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5322 cur_arg++;
5323 }
5324#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005325 /* comment for this tcpcheck line */
5326 else if (strcmp(args[cur_arg], "comment") == 0) {
5327 if (!*args[cur_arg + 1]) {
5328 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5329 file, linenum, args[cur_arg]);
5330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
5332 }
5333 tcpcheck->comment = strdup(args[cur_arg + 1]);
5334 cur_arg += 2;
5335 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005336 else {
5337#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005338 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 +01005339#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005340 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 +01005341#endif /* USE_OPENSSL */
5342 file, linenum, args[0], args[1], args[cur_arg]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346
5347 }
5348
5349 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5350 }
5351 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005352 if (! *(args[2]) ) {
5353 /* SEND string expected */
5354 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5355 file, linenum, args[0], args[1], args[2]);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 } else {
5359 struct tcpcheck_rule *tcpcheck;
5360
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005361 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005362
5363 tcpcheck->action = TCPCHK_ACT_SEND;
5364 tcpcheck->string_len = strlen(args[2]);
5365 tcpcheck->string = strdup(args[2]);
5366 tcpcheck->expect_regex = NULL;
5367
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005368 /* comment for this tcpcheck line */
5369 if (strcmp(args[3], "comment") == 0) {
5370 if (!*args[4]) {
5371 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5372 file, linenum, args[3]);
5373 err_code |= ERR_ALERT | ERR_FATAL;
5374 goto out;
5375 }
5376 tcpcheck->comment = strdup(args[4]);
5377 }
5378
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005379 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5380 }
5381 }
5382 else if (strcmp(args[1], "send-binary") == 0) {
5383 if (! *(args[2]) ) {
5384 /* SEND binary string expected */
5385 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5386 file, linenum, args[0], args[1], args[2]);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 } else {
5390 struct tcpcheck_rule *tcpcheck;
5391 char *err = NULL;
5392
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005393 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005394
5395 tcpcheck->action = TCPCHK_ACT_SEND;
5396 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5397 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5398 file, linenum, args[0], args[1], args[2], err);
5399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
5402 tcpcheck->expect_regex = NULL;
5403
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005404 /* comment for this tcpcheck line */
5405 if (strcmp(args[3], "comment") == 0) {
5406 if (!*args[4]) {
5407 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5408 file, linenum, args[3]);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412 tcpcheck->comment = strdup(args[4]);
5413 }
5414
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005415 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5416 }
5417 }
5418 else if (strcmp(args[1], "expect") == 0) {
5419 const char *ptr_arg;
5420 int cur_arg;
5421 int inverse = 0;
5422
5423 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5424 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
5428
5429 cur_arg = 2;
5430 /* consider exclamation marks, sole or at the beginning of a word */
5431 while (*(ptr_arg = args[cur_arg])) {
5432 while (*ptr_arg == '!') {
5433 inverse = !inverse;
5434 ptr_arg++;
5435 }
5436 if (*ptr_arg)
5437 break;
5438 cur_arg++;
5439 }
5440 /* now ptr_arg points to the beginning of a word past any possible
5441 * exclamation mark, and cur_arg is the argument which holds this word.
5442 */
5443 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005444 struct tcpcheck_rule *tcpcheck;
5445 char *err = NULL;
5446
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005447 if (!*(args[cur_arg + 1])) {
5448 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5449 file, linenum, args[0], args[1], ptr_arg);
5450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005453
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005454 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005455
5456 tcpcheck->action = TCPCHK_ACT_EXPECT;
5457 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5458 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5459 file, linenum, args[0], args[1], args[2], err);
5460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
5462 }
5463 tcpcheck->expect_regex = NULL;
5464 tcpcheck->inverse = inverse;
5465
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005466 /* tcpcheck comment */
5467 cur_arg += 2;
5468 if (strcmp(args[cur_arg], "comment") == 0) {
5469 if (!*args[cur_arg + 1]) {
5470 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5471 file, linenum, args[cur_arg + 1]);
5472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
5475 tcpcheck->comment = strdup(args[cur_arg + 1]);
5476 }
5477
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005478 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5479 }
5480 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005481 struct tcpcheck_rule *tcpcheck;
5482
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005483 if (!*(args[cur_arg + 1])) {
5484 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5485 file, linenum, args[0], args[1], ptr_arg);
5486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005489
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005490 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005491
5492 tcpcheck->action = TCPCHK_ACT_EXPECT;
5493 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5494 tcpcheck->string = strdup(args[cur_arg + 1]);
5495 tcpcheck->expect_regex = NULL;
5496 tcpcheck->inverse = inverse;
5497
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005498 /* tcpcheck comment */
5499 cur_arg += 2;
5500 if (strcmp(args[cur_arg], "comment") == 0) {
5501 if (!*args[cur_arg + 1]) {
5502 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5503 file, linenum, args[cur_arg + 1]);
5504 err_code |= ERR_ALERT | ERR_FATAL;
5505 goto out;
5506 }
5507 tcpcheck->comment = strdup(args[cur_arg + 1]);
5508 }
5509
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005510 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5511 }
5512 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005513 struct tcpcheck_rule *tcpcheck;
5514
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005515 if (!*(args[cur_arg + 1])) {
5516 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5517 file, linenum, args[0], args[1], ptr_arg);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005521
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005522 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005523
5524 tcpcheck->action = TCPCHK_ACT_EXPECT;
5525 tcpcheck->string_len = 0;
5526 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005527 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5528 error = NULL;
5529 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5530 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5531 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5532 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
5535 }
5536 tcpcheck->inverse = inverse;
5537
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005538 /* tcpcheck comment */
5539 cur_arg += 2;
5540 if (strcmp(args[cur_arg], "comment") == 0) {
5541 if (!*args[cur_arg + 1]) {
5542 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5543 file, linenum, args[cur_arg + 1]);
5544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
5546 }
5547 tcpcheck->comment = strdup(args[cur_arg + 1]);
5548 }
5549
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005550 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5551 }
5552 else {
5553 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5554 file, linenum, args[0], args[1], ptr_arg);
5555 err_code |= ERR_ALERT | ERR_FATAL;
5556 goto out;
5557 }
5558 }
5559 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005560 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005561 err_code |= ERR_ALERT | ERR_FATAL;
5562 goto out;
5563 }
5564 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005565 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005566 if (curproxy == &defproxy) {
5567 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005570 }
5571
Willy Tarreaub80c2302007-11-30 20:51:32 +01005572 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005574
5575 if (strcmp(args[1], "fail") == 0) {
5576 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005577 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005578 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5579 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005580 err_code |= ERR_ALERT | ERR_FATAL;
5581 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005582 }
5583
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005584 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5585 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5586 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005589 }
5590 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5591 }
5592 else {
5593 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005596 }
5597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598#ifdef TPROXY
5599 else if (!strcmp(args[0], "transparent")) {
5600 /* enable transparent proxy connections */
5601 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005602 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 }
5605#endif
5606 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005607 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005608 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005609
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 if (*(args[1]) == 0) {
5611 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 }
5615 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005616 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005618 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005619 else if (!strcmp(args[0], "backlog")) { /* backlog */
5620 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005621 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005622
5623 if (*(args[1]) == 0) {
5624 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005627 }
5628 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5630 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005631 }
Willy Tarreau86034312006-12-29 00:10:33 +01005632 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005633 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005634 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005635
Willy Tarreau86034312006-12-29 00:10:33 +01005636 if (*(args[1]) == 0) {
5637 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005640 }
5641 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005642 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5643 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5646 if (*(args[1]) == 0) {
5647 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005648 err_code |= ERR_ALERT | ERR_FATAL;
5649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005651 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5652 if (err) {
5653 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5654 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005657 }
5658 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005659 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
5662 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005663 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005664 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005665 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005666
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 if (curproxy == &defproxy) {
5668 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005669 err_code |= ERR_ALERT | ERR_FATAL;
5670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005672 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005674
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005675 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005676 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005677 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005678 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005679 goto out;
5680 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005681
5682 proto = protocol_by_family(sk->ss_family);
5683 if (!proto || !proto->connect) {
5684 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5685 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
5688 }
5689
5690 if (port1 != port2) {
5691 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5692 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005696
5697 if (!port1) {
5698 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5699 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
5702 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005703
William Lallemanddf1425a2015-04-28 20:17:49 +02005704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5705 goto out;
5706
Willy Tarreaud5191e72010-02-09 20:50:45 +01005707 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005708 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
5710 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005712 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005713
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005714 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5715 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005720 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005721 /**
5722 * The syntax for hash-type config element is
5723 * hash-type {map-based|consistent} [[<algo>] avalanche]
5724 *
5725 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5726 */
5727 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005728
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005729 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5730 err_code |= ERR_WARN;
5731
5732 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005733 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5734 }
5735 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005736 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5737 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005738 else if (strcmp(args[1], "avalanche") == 0) {
5739 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]);
5740 err_code |= ERR_ALERT | ERR_FATAL;
5741 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005742 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005743 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005744 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
5747 }
Bhaskar98634f02013-10-29 23:30:51 -04005748
5749 /* set the hash function to use */
5750 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005751 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005752 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005753
5754 /* if consistent with no argument, then avalanche modifier is also applied */
5755 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5756 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005757 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005758 /* set the hash function */
5759 if (!strcmp(args[2], "sdbm")) {
5760 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5761 }
5762 else if (!strcmp(args[2], "djb2")) {
5763 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005764 }
5765 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005766 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005767 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005768 else if (!strcmp(args[2], "crc32")) {
5769 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5770 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005771 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005772 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 -05005773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
5775 }
5776
5777 /* set the hash modifier */
5778 if (!strcmp(args[3], "avalanche")) {
5779 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5780 }
5781 else if (*args[3]) {
5782 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5783 err_code |= ERR_ALERT | ERR_FATAL;
5784 goto out;
5785 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005786 }
William Lallemanda73203e2012-03-12 12:48:57 +01005787 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005788 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5789 if (*(args[1]) == 0) {
5790 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5791 err_code |= ERR_ALERT | ERR_FATAL;
5792 goto out;
5793 }
5794 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5795 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5796 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
5799 }
5800 }
William Lallemanda73203e2012-03-12 12:48:57 +01005801 else if (strcmp(args[0], "unique-id-format") == 0) {
5802 if (!*(args[1])) {
5803 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
5806 }
William Lallemand3203ff42012-11-11 17:30:56 +01005807 if (*(args[2])) {
5808 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5809 err_code |= ERR_ALERT | ERR_FATAL;
5810 goto out;
5811 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005812 free(curproxy->conf.uniqueid_format_string);
5813 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005814
Willy Tarreau62a61232013-04-12 18:13:46 +02005815 free(curproxy->conf.uif_file);
5816 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5817 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005818 }
William Lallemanda73203e2012-03-12 12:48:57 +01005819
5820 else if (strcmp(args[0], "unique-id-header") == 0) {
5821 if (!*(args[1])) {
5822 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
5825 }
5826 free(curproxy->header_unique_id);
5827 curproxy->header_unique_id = strdup(args[1]);
5828 }
5829
William Lallemand723b73a2012-02-08 16:37:49 +01005830 else if (strcmp(args[0], "log-format") == 0) {
5831 if (!*(args[1])) {
5832 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5833 err_code |= ERR_ALERT | ERR_FATAL;
5834 goto out;
5835 }
William Lallemand3203ff42012-11-11 17:30:56 +01005836 if (*(args[2])) {
5837 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5838 err_code |= ERR_ALERT | ERR_FATAL;
5839 goto out;
5840 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005841
Willy Tarreau62a61232013-04-12 18:13:46 +02005842 if (curproxy->conf.logformat_string != default_http_log_format &&
5843 curproxy->conf.logformat_string != default_tcp_log_format &&
5844 curproxy->conf.logformat_string != clf_http_log_format)
5845 free(curproxy->conf.logformat_string);
5846 curproxy->conf.logformat_string = strdup(args[1]);
5847
5848 free(curproxy->conf.lfs_file);
5849 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5850 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005851
5852 /* get a chance to improve log-format error reporting by
5853 * reporting the correct line-number when possible.
5854 */
5855 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5856 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5857 file, linenum, curproxy->id);
5858 err_code |= ERR_WARN;
5859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005861 else if (!strcmp(args[0], "log-format-sd")) {
5862 if (!*(args[1])) {
5863 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
5866 }
5867 if (*(args[2])) {
5868 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5869 err_code |= ERR_ALERT | ERR_FATAL;
5870 goto out;
5871 }
5872
5873 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5874 free(curproxy->conf.logformat_sd_string);
5875 curproxy->conf.logformat_sd_string = strdup(args[1]);
5876
5877 free(curproxy->conf.lfsd_file);
5878 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5879 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5880
5881 /* get a chance to improve log-format-sd error reporting by
5882 * reporting the correct line-number when possible.
5883 */
5884 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5885 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5886 file, linenum, curproxy->id);
5887 err_code |= ERR_WARN;
5888 }
5889 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005890 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5891 if (*(args[1]) == 0) {
5892 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
5895 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005896 chunk_destroy(&curproxy->log_tag);
5897 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005898 }
William Lallemand0f99e342011-10-12 17:50:54 +02005899 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5900 /* delete previous herited or defined syslog servers */
5901 struct logsrv *back;
5902
5903 if (*(args[1]) != 0) {
5904 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5905 err_code |= ERR_ALERT | ERR_FATAL;
5906 goto out;
5907 }
5908
William Lallemand723b73a2012-02-08 16:37:49 +01005909 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5910 LIST_DEL(&tmplogsrv->list);
5911 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005912 }
5913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005915 struct logsrv *logsrv;
5916
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005918 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005919 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005920 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005921 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005922 LIST_INIT(&node->list);
5923 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 }
5926 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005927 struct sockaddr_storage *sk;
5928 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005929 int arg = 0;
5930 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005931
Vincent Bernat02779b62016-04-03 13:48:43 +02005932 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933
Willy Tarreau18324f52014-06-27 18:10:07 +02005934 /* just after the address, a length may be specified */
5935 if (strcmp(args[arg+2], "len") == 0) {
5936 len = atoi(args[arg+3]);
5937 if (len < 80 || len > 65535) {
5938 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5939 file, linenum, args[arg+3]);
5940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
5942 }
5943 logsrv->maxlen = len;
5944
5945 /* skip these two args */
5946 arg += 2;
5947 }
5948 else
5949 logsrv->maxlen = MAX_SYSLOG_LEN;
5950
5951 if (logsrv->maxlen > global.max_syslog_len) {
5952 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02005953 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
5954 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
5955 logline = my_realloc2(logline, global.max_syslog_len + 1);
5956 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005957 }
5958
Dragan Dosen1322d092015-09-22 16:05:32 +02005959 /* after the length, a format may be specified */
5960 if (strcmp(args[arg+2], "format") == 0) {
5961 logsrv->format = get_log_format(args[arg+3]);
5962 if (logsrv->format < 0) {
5963 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
5967
5968 /* skip these two args */
5969 arg += 2;
5970 }
5971
William Lallemanddf1425a2015-04-28 20:17:49 +02005972 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5973 goto out;
5974
Willy Tarreau18324f52014-06-27 18:10:07 +02005975 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005976 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005977 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005978 err_code |= ERR_ALERT | ERR_FATAL;
5979 goto out;
5980
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 }
5982
William Lallemand0f99e342011-10-12 17:50:54 +02005983 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005984 if (*(args[arg+3])) {
5985 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005986 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005987 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005988 err_code |= ERR_ALERT | ERR_FATAL;
5989 goto out;
5990
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 }
5992 }
5993
William Lallemand0f99e342011-10-12 17:50:54 +02005994 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005995 if (*(args[arg+4])) {
5996 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005997 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005998 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005999 err_code |= ERR_ALERT | ERR_FATAL;
6000 goto out;
6001
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006002 }
6003 }
6004
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006005 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006006 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006007 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006008 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006009 goto out;
6010 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006011
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006012 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006013
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006014 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006015 if (port1 != port2) {
6016 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6017 file, linenum, args[0], args[1]);
6018 err_code |= ERR_ALERT | ERR_FATAL;
6019 goto out;
6020 }
6021
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006022 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006023 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006024 }
William Lallemand0f99e342011-10-12 17:50:54 +02006025
6026 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027 }
6028 else {
6029 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6030 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006031 err_code |= ERR_ALERT | ERR_FATAL;
6032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 }
6034 }
6035 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006036 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006037 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006038 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006039 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006040
Willy Tarreau977b8e42006-12-29 14:19:17 +01006041 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006042 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006043
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006045 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6046 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006047 err_code |= ERR_ALERT | ERR_FATAL;
6048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006050
6051 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006052 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6053 free(curproxy->conn_src.iface_name);
6054 curproxy->conn_src.iface_name = NULL;
6055 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006056
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006057 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006058 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006059 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006060 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006061 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006062 goto out;
6063 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006064
6065 proto = protocol_by_family(sk->ss_family);
6066 if (!proto || !proto->connect) {
6067 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006068 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006069 err_code |= ERR_ALERT | ERR_FATAL;
6070 goto out;
6071 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006072
6073 if (port1 != port2) {
6074 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6075 file, linenum, args[0], args[1]);
6076 err_code |= ERR_ALERT | ERR_FATAL;
6077 goto out;
6078 }
6079
Willy Tarreauef9a3602012-12-08 22:29:20 +01006080 curproxy->conn_src.source_addr = *sk;
6081 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006082
6083 cur_arg = 2;
6084 while (*(args[cur_arg])) {
6085 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006086#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006087 if (!*args[cur_arg + 1]) {
6088 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6089 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006090 err_code |= ERR_ALERT | ERR_FATAL;
6091 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006092 }
6093
6094 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006095 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6096 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006097 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006098 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6099 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006100 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6101 char *name, *end;
6102
6103 name = args[cur_arg+1] + 7;
6104 while (isspace(*name))
6105 name++;
6106
6107 end = name;
6108 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6109 end++;
6110
Willy Tarreauef9a3602012-12-08 22:29:20 +01006111 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6112 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6113 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6114 curproxy->conn_src.bind_hdr_len = end - name;
6115 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6116 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6117 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006118
6119 /* now look for an occurrence number */
6120 while (isspace(*end))
6121 end++;
6122 if (*end == ',') {
6123 end++;
6124 name = end;
6125 if (*end == '-')
6126 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006127 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006128 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006129 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006130 }
6131
Willy Tarreauef9a3602012-12-08 22:29:20 +01006132 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006133 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6134 " occurrences values smaller than %d.\n",
6135 file, linenum, MAX_HDR_HISTORY);
6136 err_code |= ERR_ALERT | ERR_FATAL;
6137 goto out;
6138 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006139 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006140 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006141
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006142 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006143 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006144 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006145 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006146 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006147 goto out;
6148 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006149
6150 proto = protocol_by_family(sk->ss_family);
6151 if (!proto || !proto->connect) {
6152 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6153 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
6156 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006157
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006158 if (port1 != port2) {
6159 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6160 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006161 err_code |= ERR_ALERT | ERR_FATAL;
6162 goto out;
6163 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006164 curproxy->conn_src.tproxy_addr = *sk;
6165 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006166 }
6167 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006168#else /* no TPROXY support */
6169 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006170 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006171 err_code |= ERR_ALERT | ERR_FATAL;
6172 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006173#endif
6174 cur_arg += 2;
6175 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006176 }
6177
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006178 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6179#ifdef SO_BINDTODEVICE
6180 if (!*args[cur_arg + 1]) {
6181 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6182 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006183 err_code |= ERR_ALERT | ERR_FATAL;
6184 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006185 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006186 free(curproxy->conn_src.iface_name);
6187 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6188 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006189 global.last_checks |= LSTCHK_NETADM;
6190#else
6191 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6192 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006193 err_code |= ERR_ALERT | ERR_FATAL;
6194 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006195#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006196 cur_arg += 2;
6197 continue;
6198 }
6199 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006200 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006201 err_code |= ERR_ALERT | ERR_FATAL;
6202 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006205 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6206 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6207 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006208 err_code |= ERR_ALERT | ERR_FATAL;
6209 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006212 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006213 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006215 err_code |= ERR_ALERT | ERR_FATAL;
6216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006218
6219 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006220 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006221 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006222 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006224 }
6225 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006226 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006227 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006228 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006229 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006231 }
6232 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006233 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006234 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006235 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006236 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006238 }
6239 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006240 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006241 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006242 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006243 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 }
6246 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006247 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006248 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006249 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006250 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006252 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006253 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006254 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006255 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006256 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006257 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006258 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006261 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006262 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006267
6268 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006269 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006270 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006271 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 }
6274 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006276 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006277 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 }
6281 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006283 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006284 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 }
6288 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006290 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006291 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006294 }
6295 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006296 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006297 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006298 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006299 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006302 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006304 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006305 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006307 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006310 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006311
Willy Tarreaubaaee002006-06-26 02:48:02 +02006312 if (curproxy == &defproxy) {
6313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006317 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006318 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319
Willy Tarreaubaaee002006-06-26 02:48:02 +02006320 if (*(args[1]) == 0) {
6321 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006322 err_code |= ERR_ALERT | ERR_FATAL;
6323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006325
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006326 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006327 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6328 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6329 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006330 err_code |= ERR_ALERT | ERR_FATAL;
6331 goto out;
6332 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006333 err_code |= warnif_cond_conflicts(cond,
6334 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6335 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006336 }
6337 else if (*args[2]) {
6338 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6339 file, linenum, args[0], args[2]);
6340 err_code |= ERR_ALERT | ERR_FATAL;
6341 goto out;
6342 }
6343
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006344 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006345 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006346 wl->s = strdup(args[1]);
6347 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006348 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 }
6350 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006354 err_code |= ERR_ALERT | ERR_FATAL;
6355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006357
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006359 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006360 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 }
6364 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006366 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
6371 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006373 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 }
6378 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006382 err_code |= ERR_ALERT | ERR_FATAL;
6383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 }
6385
Willy Tarreauade5ec42010-01-28 19:33:49 +01006386 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006387 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006388 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 }
6392 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006394 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006395 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006396 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 }
6399 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006400 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006401 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006402 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006403 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 }
6406 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006407 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006408
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409 if (curproxy == &defproxy) {
6410 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006411 err_code |= ERR_ALERT | ERR_FATAL;
6412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006414 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006415 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417 if (*(args[1]) == 0) {
6418 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006419 err_code |= ERR_ALERT | ERR_FATAL;
6420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 }
6422
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006423 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006424 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6425 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6426 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006427 err_code |= ERR_ALERT | ERR_FATAL;
6428 goto out;
6429 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006430 err_code |= warnif_cond_conflicts(cond,
6431 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6432 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006433 }
6434 else if (*args[2]) {
6435 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6436 file, linenum, args[0], args[2]);
6437 err_code |= ERR_ALERT | ERR_FATAL;
6438 goto out;
6439 }
6440
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006441 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006442 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006443 wl->s = strdup(args[1]);
6444 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445 }
6446 else if (!strcmp(args[0], "errorloc") ||
6447 !strcmp(args[0], "errorloc302") ||
6448 !strcmp(args[0], "errorloc303")) { /* error location */
6449 int errnum, errlen;
6450 char *err;
6451
Willy Tarreau977b8e42006-12-29 14:19:17 +01006452 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006453 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006454
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006456 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006457 err_code |= ERR_ALERT | ERR_FATAL;
6458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459 }
6460
6461 errnum = atol(args[1]);
6462 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006463 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6464 err = malloc(errlen);
6465 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006466 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006467 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6468 err = malloc(errlen);
6469 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 }
6471
Willy Tarreau0f772532006-12-23 20:51:41 +01006472 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6473 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006474 chunk_destroy(&curproxy->errmsg[rc]);
6475 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006476 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006479
6480 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006481 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6482 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 free(err);
6484 }
6485 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006486 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6487 int errnum, errlen, fd;
6488 char *err;
6489 struct stat stat;
6490
6491 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006492 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006493
6494 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006495 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006496 err_code |= ERR_ALERT | ERR_FATAL;
6497 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006498 }
6499
6500 fd = open(args[2], O_RDONLY);
6501 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6502 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6503 file, linenum, args[2], args[1]);
6504 if (fd >= 0)
6505 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006506 err_code |= ERR_ALERT | ERR_FATAL;
6507 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006508 }
6509
Willy Tarreau27a674e2009-08-17 07:23:33 +02006510 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006511 errlen = stat.st_size;
6512 } else {
6513 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006514 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006515 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006516 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006517 }
6518
6519 err = malloc(errlen); /* malloc() must succeed during parsing */
6520 errnum = read(fd, err, errlen);
6521 if (errnum != errlen) {
6522 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6523 file, linenum, args[2], args[1]);
6524 close(fd);
6525 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006526 err_code |= ERR_ALERT | ERR_FATAL;
6527 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006528 }
6529 close(fd);
6530
6531 errnum = atol(args[1]);
6532 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6533 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006534 chunk_destroy(&curproxy->errmsg[rc]);
6535 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006536 break;
6537 }
6538 }
6539
6540 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006541 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6542 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006543 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006544 free(err);
6545 }
6546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006548 struct cfg_kw_list *kwl;
6549 int index;
6550
6551 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6552 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6553 if (kwl->kw[index].section != CFG_LISTEN)
6554 continue;
6555 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6556 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006557 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006558 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006559 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006560 err_code |= ERR_ALERT | ERR_FATAL;
6561 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006562 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006563 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006564 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006565 err_code |= ERR_WARN;
6566 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006567 }
Willy Tarreau93893792009-07-23 13:19:11 +02006568 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006569 }
6570 }
6571 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006572
Willy Tarreau6daf3432008-01-22 16:44:08 +01006573 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006574 err_code |= ERR_ALERT | ERR_FATAL;
6575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006576 }
Willy Tarreau93893792009-07-23 13:19:11 +02006577 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006578 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006579 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580}
6581
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006582int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006583cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6584{
6585#ifdef CONFIG_HAP_NS
6586 const char *err;
6587 const char *item = args[0];
6588
6589 if (!strcmp(item, "namespace_list")) {
6590 return 0;
6591 }
6592 else if (!strcmp(item, "namespace")) {
6593 size_t idx = 1;
6594 const char *current;
6595 while (*(current = args[idx++])) {
6596 err = invalid_char(current);
6597 if (err) {
6598 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6599 file, linenum, *err, item, current);
6600 return ERR_ALERT | ERR_FATAL;
6601 }
6602
6603 if (netns_store_lookup(current, strlen(current))) {
6604 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6605 file, linenum, current);
6606 return ERR_ALERT | ERR_FATAL;
6607 }
6608 if (!netns_store_insert(current)) {
6609 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6610 file, linenum, current);
6611 return ERR_ALERT | ERR_FATAL;
6612 }
6613 }
6614 }
6615
6616 return 0;
6617#else
6618 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6619 file, linenum);
6620 return ERR_ALERT | ERR_FATAL;
6621#endif
6622}
6623
6624int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006625cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6626{
6627
6628 int err_code = 0;
6629 const char *err;
6630
6631 if (!strcmp(args[0], "userlist")) { /* new userlist */
6632 struct userlist *newul;
6633
6634 if (!*args[1]) {
6635 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6636 file, linenum, args[0]);
6637 err_code |= ERR_ALERT | ERR_FATAL;
6638 goto out;
6639 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006640 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6641 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006642
6643 err = invalid_char(args[1]);
6644 if (err) {
6645 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6646 file, linenum, *err, args[0], args[1]);
6647 err_code |= ERR_ALERT | ERR_FATAL;
6648 goto out;
6649 }
6650
6651 for (newul = userlist; newul; newul = newul->next)
6652 if (!strcmp(newul->name, args[1])) {
6653 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6654 file, linenum, args[1]);
6655 err_code |= ERR_WARN;
6656 goto out;
6657 }
6658
Vincent Bernat02779b62016-04-03 13:48:43 +02006659 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660 if (!newul) {
6661 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6662 err_code |= ERR_ALERT | ERR_ABORT;
6663 goto out;
6664 }
6665
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006666 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006667 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006668 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6669 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006670 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006671 goto out;
6672 }
6673
6674 newul->next = userlist;
6675 userlist = newul;
6676
6677 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006678 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006679 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006680 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006681
6682 if (!*args[1]) {
6683 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6684 file, linenum, args[0]);
6685 err_code |= ERR_ALERT | ERR_FATAL;
6686 goto out;
6687 }
6688
6689 err = invalid_char(args[1]);
6690 if (err) {
6691 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6692 file, linenum, *err, args[0], args[1]);
6693 err_code |= ERR_ALERT | ERR_FATAL;
6694 goto out;
6695 }
6696
William Lallemand4ac9f542015-05-28 18:03:51 +02006697 if (!userlist)
6698 goto out;
6699
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006700 for (ag = userlist->groups; ag; ag = ag->next)
6701 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006702 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6703 file, linenum, args[1], userlist->name);
6704 err_code |= ERR_ALERT;
6705 goto out;
6706 }
6707
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006708 ag = calloc(1, sizeof(*ag));
6709 if (!ag) {
6710 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6711 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006712 goto out;
6713 }
6714
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006715 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006716 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006717 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6718 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006719 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006720 goto out;
6721 }
6722
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006723 cur_arg = 2;
6724
6725 while (*args[cur_arg]) {
6726 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006727 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006728 cur_arg += 2;
6729 continue;
6730 } else {
6731 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6732 file, linenum, args[0]);
6733 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006734 free(ag->groupusers);
6735 free(ag->name);
6736 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006737 goto out;
6738 }
6739 }
6740
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006741 ag->next = userlist->groups;
6742 userlist->groups = ag;
6743
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006744 } else if (!strcmp(args[0], "user")) { /* new user */
6745 struct auth_users *newuser;
6746 int cur_arg;
6747
6748 if (!*args[1]) {
6749 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6750 file, linenum, args[0]);
6751 err_code |= ERR_ALERT | ERR_FATAL;
6752 goto out;
6753 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006754 if (!userlist)
6755 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006756
6757 for (newuser = userlist->users; newuser; newuser = newuser->next)
6758 if (!strcmp(newuser->user, args[1])) {
6759 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6760 file, linenum, args[1], userlist->name);
6761 err_code |= ERR_ALERT;
6762 goto out;
6763 }
6764
Vincent Bernat02779b62016-04-03 13:48:43 +02006765 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766 if (!newuser) {
6767 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6768 err_code |= ERR_ALERT | ERR_ABORT;
6769 goto out;
6770 }
6771
6772 newuser->user = strdup(args[1]);
6773
6774 newuser->next = userlist->users;
6775 userlist->users = newuser;
6776
6777 cur_arg = 2;
6778
6779 while (*args[cur_arg]) {
6780 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006781#ifdef CONFIG_HAP_CRYPT
6782 if (!crypt("", args[cur_arg + 1])) {
6783 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6784 file, linenum, newuser->user);
6785 err_code |= ERR_ALERT | ERR_FATAL;
6786 goto out;
6787 }
6788#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006789 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6790 file, linenum);
6791 err_code |= ERR_ALERT;
6792#endif
6793 newuser->pass = strdup(args[cur_arg + 1]);
6794 cur_arg += 2;
6795 continue;
6796 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6797 newuser->pass = strdup(args[cur_arg + 1]);
6798 newuser->flags |= AU_O_INSECURE;
6799 cur_arg += 2;
6800 continue;
6801 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006802 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803 cur_arg += 2;
6804 continue;
6805 } else {
6806 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6807 file, linenum, args[0]);
6808 err_code |= ERR_ALERT | ERR_FATAL;
6809 goto out;
6810 }
6811 }
6812 } else {
6813 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6814 err_code |= ERR_ALERT | ERR_FATAL;
6815 }
6816
6817out:
6818 return err_code;
6819}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006820
Christopher Faulet79bdef32016-11-04 22:36:15 +01006821int
6822cfg_parse_scope(const char *file, int linenum, char *line)
6823{
6824 char *beg, *end, *scope = NULL;
6825 int err_code = 0;
6826 const char *err;
6827
6828 beg = line + 1;
6829 end = strchr(beg, ']');
6830
6831 /* Detect end of scope declaration */
6832 if (!end || end == beg) {
6833 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6834 file, linenum);
6835 err_code |= ERR_ALERT | ERR_FATAL;
6836 goto out;
6837 }
6838
6839 /* Get scope name and check its validity */
6840 scope = my_strndup(beg, end-beg);
6841 err = invalid_char(scope);
6842 if (err) {
6843 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6844 file, linenum, *err);
6845 err_code |= ERR_ALERT | ERR_ABORT;
6846 goto out;
6847 }
6848
6849 /* Be sure to have a scope declaration alone on its line */
6850 line = end+1;
6851 while (isspace((unsigned char)*line))
6852 line++;
6853 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6854 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6855 file, linenum, *line);
6856 err_code |= ERR_ALERT | ERR_ABORT;
6857 goto out;
6858 }
6859
6860 /* We have a valid scope declaration, save it */
6861 free(cfg_scope);
6862 cfg_scope = scope;
6863 scope = NULL;
6864
6865 out:
6866 free(scope);
6867 return err_code;
6868}
6869
Willy Tarreaubaaee002006-06-26 02:48:02 +02006870/*
6871 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006872 * Returns the error code, 0 if OK, or any combination of :
6873 * - ERR_ABORT: must abort ASAP
6874 * - ERR_FATAL: we can continue parsing but not start the service
6875 * - ERR_WARN: a warning has been emitted
6876 * - ERR_ALERT: an alert has been emitted
6877 * Only the two first ones can stop processing, the two others are just
6878 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006879 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006880int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006881{
William Lallemand64e84512015-05-12 14:25:37 +02006882 char *thisline;
6883 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006884 FILE *f;
6885 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006886 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006887 struct cfg_section *cs = NULL;
6888 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006889 int readbytes = 0;
6890
6891 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006892 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006893 return -1;
6894 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006895
David Carlier97880bb2016-04-08 10:35:26 +01006896 if ((f=fopen(file,"r")) == NULL) {
6897 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006898 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006900
William Lallemandb2f07452015-05-12 14:27:13 +02006901next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006902 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006903 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006904 char *end;
6905 char *args[MAX_LINE_ARGS + 1];
6906 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006907 int dquote = 0; /* double quote */
6908 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006909
Willy Tarreaubaaee002006-06-26 02:48:02 +02006910 linenum++;
6911
6912 end = line + strlen(line);
6913
William Lallemand64e84512015-05-12 14:25:37 +02006914 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006915 /* Check if we reached the limit and the last char is not \n.
6916 * Watch out for the last line without the terminating '\n'!
6917 */
William Lallemand64e84512015-05-12 14:25:37 +02006918 char *newline;
6919 int newlinesize = linesize * 2;
6920
6921 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6922 if (newline == NULL) {
6923 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6924 file, linenum);
6925 err_code |= ERR_ALERT | ERR_FATAL;
6926 continue;
6927 }
6928
6929 readbytes = linesize - 1;
6930 linesize = newlinesize;
6931 thisline = newline;
6932 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006933 }
6934
William Lallemand64e84512015-05-12 14:25:37 +02006935 readbytes = 0;
6936
Willy Tarreaubaaee002006-06-26 02:48:02 +02006937 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006938 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006939 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006940
Christopher Faulet79bdef32016-11-04 22:36:15 +01006941
6942 if (*line == '[') {/* This is the begining if a scope */
6943 err_code |= cfg_parse_scope(file, linenum, line);
6944 goto next_line;
6945 }
6946
Willy Tarreaubaaee002006-06-26 02:48:02 +02006947 arg = 0;
6948 args[arg] = line;
6949
6950 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006951 if (*line == '"' && !squote) { /* double quote outside single quotes */
6952 if (dquote)
6953 dquote = 0;
6954 else
6955 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006956 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006957 end--;
6958 }
6959 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6960 if (squote)
6961 squote = 0;
6962 else
6963 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006964 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006965 end--;
6966 }
6967 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006968 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6969 * C equivalent value. Other combinations left unchanged (eg: \1).
6970 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006971 int skip = 0;
6972 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6973 *line = line[1];
6974 skip = 1;
6975 }
6976 else if (line[1] == 'r') {
6977 *line = '\r';
6978 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006980 else if (line[1] == 'n') {
6981 *line = '\n';
6982 skip = 1;
6983 }
6984 else if (line[1] == 't') {
6985 *line = '\t';
6986 skip = 1;
6987 }
6988 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006989 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006990 unsigned char hex1, hex2;
6991 hex1 = toupper(line[2]) - '0';
6992 hex2 = toupper(line[3]) - '0';
6993 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6994 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6995 *line = (hex1<<4) + hex2;
6996 skip = 3;
6997 }
6998 else {
6999 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007000 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007001 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007002 } else if (line[1] == '"') {
7003 *line = '"';
7004 skip = 1;
7005 } else if (line[1] == '\'') {
7006 *line = '\'';
7007 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007008 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7009 *line = '$';
7010 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011 }
7012 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007013 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007014 end -= skip;
7015 }
7016 line++;
7017 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007018 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007019 /* end of string, end of loop */
7020 *line = 0;
7021 break;
7022 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007023 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007025 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007026 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007027 line++;
7028 args[++arg] = line;
7029 }
William Lallemandb2f07452015-05-12 14:27:13 +02007030 else if (dquote && *line == '$') {
7031 /* environment variables are evaluated inside double quotes */
7032 char *var_beg;
7033 char *var_end;
7034 char save_char;
7035 char *value;
7036 int val_len;
7037 int newlinesize;
7038 int braces = 0;
7039
7040 var_beg = line + 1;
7041 var_end = var_beg;
7042
7043 if (*var_beg == '{') {
7044 var_beg++;
7045 var_end++;
7046 braces = 1;
7047 }
7048
7049 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7050 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7051 err_code |= ERR_ALERT | ERR_FATAL;
7052 goto next_line; /* skip current line */
7053 }
7054
7055 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7056 var_end++;
7057
7058 save_char = *var_end;
7059 *var_end = '\0';
7060 value = getenv(var_beg);
7061 *var_end = save_char;
7062 val_len = value ? strlen(value) : 0;
7063
7064 if (braces) {
7065 if (*var_end == '}') {
7066 var_end++;
7067 braces = 0;
7068 } else {
7069 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7070 err_code |= ERR_ALERT | ERR_FATAL;
7071 goto next_line; /* skip current line */
7072 }
7073 }
7074
7075 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7076
7077 /* if not enough space in thisline */
7078 if (newlinesize > linesize) {
7079 char *newline;
7080
7081 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7082 if (newline == NULL) {
7083 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7084 err_code |= ERR_ALERT | ERR_FATAL;
7085 goto next_line; /* slip current line */
7086 }
7087 /* recompute pointers if realloc returns a new pointer */
7088 if (newline != thisline) {
7089 int i;
7090 int diff;
7091
7092 for (i = 0; i <= arg; i++) {
7093 diff = args[i] - thisline;
7094 args[i] = newline + diff;
7095 }
7096
7097 diff = var_end - thisline;
7098 var_end = newline + diff;
7099 diff = end - thisline;
7100 end = newline + diff;
7101 diff = line - thisline;
7102 line = newline + diff;
7103 thisline = newline;
7104 }
7105 linesize = newlinesize;
7106 }
7107
7108 /* insert value inside the line */
7109 memmove(line + val_len, var_end, end - var_end + 1);
7110 memcpy(line, value, val_len);
7111 end += val_len - (var_end - line);
7112 line += val_len;
7113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 else {
7115 line++;
7116 }
7117 }
William Lallemandb2f07452015-05-12 14:27:13 +02007118
William Lallemandf9873ba2015-05-05 17:37:14 +02007119 if (dquote) {
7120 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7121 err_code |= ERR_ALERT | ERR_FATAL;
7122 }
7123
7124 if (squote) {
7125 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7126 err_code |= ERR_ALERT | ERR_FATAL;
7127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007128
7129 /* empty line */
7130 if (!**args)
7131 continue;
7132
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007133 if (*line) {
7134 /* we had to stop due to too many args.
7135 * Let's terminate the string, print the offending part then cut the
7136 * last arg.
7137 */
7138 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7139 line++;
7140 *line = '\0';
7141
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007142 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007143 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007144 err_code |= ERR_ALERT | ERR_FATAL;
7145 args[arg] = line;
7146 }
7147
Willy Tarreau540abe42007-05-02 20:50:16 +02007148 /* zero out remaining args and ensure that at least one entry
7149 * is zeroed out.
7150 */
7151 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007152 args[arg] = line;
7153 }
7154
Willy Tarreau3842f002009-06-14 11:39:52 +02007155 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007156 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007157 char *tmp;
7158
Willy Tarreau3842f002009-06-14 11:39:52 +02007159 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007160 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007161 for (arg=0; *args[arg+1]; arg++)
7162 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007163 *tmp = '\0'; // fix the next arg to \0
7164 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007165 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007166 else if (!strcmp(args[0], "default")) {
7167 kwm = KWM_DEF;
7168 for (arg=0; *args[arg+1]; arg++)
7169 args[arg] = args[arg+1]; // shift args after inversion
7170 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007171
William Lallemand0f99e342011-10-12 17:50:54 +02007172 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7173 strcmp(args[0], "log") != 0) {
7174 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007175 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007176 }
7177
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007178 /* detect section start */
7179 list_for_each_entry(ics, &sections, list) {
7180 if (strcmp(args[0], ics->section_name) == 0) {
7181 cursection = ics->section_name;
7182 cs = ics;
7183 break;
7184 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007185 }
7186
Willy Tarreaubaaee002006-06-26 02:48:02 +02007187 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007188 if (cs)
7189 err_code |= cs->section_parser(file, linenum, args, kwm);
7190 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007191 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007192 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007193 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007194
7195 if (err_code & ERR_ABORT)
7196 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007197 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007198 free(cfg_scope);
7199 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007200 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007201 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007202 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007203 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007204}
7205
Willy Tarreau64ab6072014-09-16 12:17:36 +02007206/* This function propagates processes from frontend <from> to backend <to> so
7207 * that it is always guaranteed that a backend pointed to by a frontend is
7208 * bound to all of its processes. After that, if the target is a "listen"
7209 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007210 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007211 * checked first to ensure that <to> is already bound to all processes of
7212 * <from>, there is no risk of looping and we ensure to follow the shortest
7213 * path to the destination.
7214 *
7215 * It is possible to set <to> to NULL for the first call so that the function
7216 * takes care of visiting the initial frontend in <from>.
7217 *
7218 * It is important to note that the function relies on the fact that all names
7219 * have already been resolved.
7220 */
7221void propagate_processes(struct proxy *from, struct proxy *to)
7222{
7223 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007224
7225 if (to) {
7226 /* check whether we need to go down */
7227 if (from->bind_proc &&
7228 (from->bind_proc & to->bind_proc) == from->bind_proc)
7229 return;
7230
7231 if (!from->bind_proc && !to->bind_proc)
7232 return;
7233
7234 to->bind_proc = from->bind_proc ?
7235 (to->bind_proc | from->bind_proc) : 0;
7236
7237 /* now propagate down */
7238 from = to;
7239 }
7240
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007241 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007242 return;
7243
Willy Tarreauf6b70012014-12-18 14:00:43 +01007244 if (from->state == PR_STSTOPPED)
7245 return;
7246
Willy Tarreau64ab6072014-09-16 12:17:36 +02007247 /* default_backend */
7248 if (from->defbe.be)
7249 propagate_processes(from, from->defbe.be);
7250
7251 /* use_backend */
7252 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007253 if (rule->dynamic)
7254 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007255 to = rule->be.backend;
7256 propagate_processes(from, to);
7257 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007258}
7259
Willy Tarreaubb925012009-07-23 13:36:36 +02007260/*
7261 * Returns the error code, 0 if OK, or any combination of :
7262 * - ERR_ABORT: must abort ASAP
7263 * - ERR_FATAL: we can continue parsing but not start the service
7264 * - ERR_WARN: a warning has been emitted
7265 * - ERR_ALERT: an alert has been emitted
7266 * Only the two first ones can stop processing, the two others are just
7267 * indicators.
7268 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007269int check_config_validity()
7270{
7271 int cfgerr = 0;
7272 struct proxy *curproxy = NULL;
7273 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007274 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007275 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007276 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007277 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007278
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007279 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007280 /*
7281 * Now, check for the integrity of all that we have collected.
7282 */
7283
7284 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007285 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007286
Willy Tarreau193b8c62012-11-22 00:17:38 +01007287 if (!global.tune.max_http_hdr)
7288 global.tune.max_http_hdr = MAX_HTTP_HDR;
7289
7290 if (!global.tune.cookie_len)
7291 global.tune.cookie_len = CAPTURE_LEN;
7292
7293 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7294
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007295 /* Post initialisation of the users and groups lists. */
7296 err_code = userlist_postinit();
7297 if (err_code != ERR_NONE)
7298 goto out;
7299
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007300 /* first, we will invert the proxy list order */
7301 curproxy = NULL;
7302 while (proxy) {
7303 struct proxy *next;
7304
7305 next = proxy->next;
7306 proxy->next = curproxy;
7307 curproxy = proxy;
7308 if (!next)
7309 break;
7310 proxy = next;
7311 }
7312
Willy Tarreau419ead82014-09-16 13:41:21 +02007313 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007314 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007315 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007316 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007317 struct act_rule *trule;
7318 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007319 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007320 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007321 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007322
Willy Tarreau050536d2012-10-04 08:47:34 +02007323 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007324 /* proxy ID not set, use automatic numbering with first
7325 * spare entry starting with next_pxid.
7326 */
7327 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7328 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7329 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007330 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007331 next_pxid++;
7332
Willy Tarreau55ea7572007-06-17 19:56:27 +02007333
Willy Tarreaubaaee002006-06-26 02:48:02 +02007334 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007335 /* ensure we don't keep listeners uselessly bound */
7336 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007337 free((void *)curproxy->table.peers.name);
7338 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007339 continue;
7340 }
7341
Willy Tarreau102df612014-05-07 23:56:38 +02007342 /* Check multi-process mode compatibility for the current proxy */
7343
7344 if (curproxy->bind_proc) {
7345 /* an explicit bind-process was specified, let's check how many
7346 * processes remain.
7347 */
David Carliere6c39412015-07-02 07:00:17 +00007348 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007349
7350 curproxy->bind_proc &= nbits(global.nbproc);
7351 if (!curproxy->bind_proc && nbproc == 1) {
7352 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);
7353 curproxy->bind_proc = 1;
7354 }
7355 else if (!curproxy->bind_proc && nbproc > 1) {
7356 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);
7357 curproxy->bind_proc = 0;
7358 }
7359 }
7360
Willy Tarreau3d209582014-05-09 17:06:11 +02007361 /* check and reduce the bind-proc of each listener */
7362 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7363 unsigned long mask;
7364
7365 if (!bind_conf->bind_proc)
7366 continue;
7367
7368 mask = nbits(global.nbproc);
7369 if (curproxy->bind_proc)
7370 mask &= curproxy->bind_proc;
7371 /* mask cannot be null here thanks to the previous checks */
7372
David Carliere6c39412015-07-02 07:00:17 +00007373 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007374 bind_conf->bind_proc &= mask;
7375
7376 if (!bind_conf->bind_proc && nbproc == 1) {
7377 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",
7378 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7379 bind_conf->bind_proc = mask & ~(mask - 1);
7380 }
7381 else if (!bind_conf->bind_proc && nbproc > 1) {
7382 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",
7383 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7384 bind_conf->bind_proc = 0;
7385 }
7386 }
7387
Willy Tarreauff01a212009-03-15 13:46:16 +01007388 switch (curproxy->mode) {
7389 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007390 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007391 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007392 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7393 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007394 cfgerr++;
7395 }
7396
7397 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007398 Warning("config : servers will be ignored for %s '%s'.\n",
7399 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007400 break;
7401
7402 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007403 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007404 break;
7405
7406 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007407 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007408 break;
7409 }
7410
Willy Tarreauf3934b82015-08-11 11:36:45 +02007411 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7412 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7413 proxy_type_str(curproxy), curproxy->id);
7414 err_code |= ERR_WARN;
7415 }
7416
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007417 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007418 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007419 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007420 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7421 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007422 cfgerr++;
7423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007424#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007425 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007426 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7427 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007428 cfgerr++;
7429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007430#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007431 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007432 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7433 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007434 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007435 }
7436 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007437 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007438 /* If no LB algo is set in a backend, and we're not in
7439 * transparent mode, dispatch mode nor proxy mode, we
7440 * want to use balance roundrobin by default.
7441 */
7442 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7443 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007444 }
7445 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007446
Willy Tarreau1620ec32011-08-06 17:05:02 +02007447 if (curproxy->options & PR_O_DISPATCH)
7448 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7449 else if (curproxy->options & PR_O_HTTP_PROXY)
7450 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7451 else if (curproxy->options & PR_O_TRANSP)
7452 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007453
Willy Tarreau1620ec32011-08-06 17:05:02 +02007454 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7455 if (curproxy->options & PR_O_DISABLE404) {
7456 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7457 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7458 err_code |= ERR_WARN;
7459 curproxy->options &= ~PR_O_DISABLE404;
7460 }
7461 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7462 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7463 "send-state", proxy_type_str(curproxy), curproxy->id);
7464 err_code |= ERR_WARN;
7465 curproxy->options &= ~PR_O2_CHK_SNDST;
7466 }
Willy Tarreauef781042010-01-27 11:53:01 +01007467 }
7468
Simon Horman98637e52014-06-20 12:30:16 +09007469 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7470 if (!global.external_check) {
7471 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7472 curproxy->id, "option external-check");
7473 cfgerr++;
7474 }
7475 if (!curproxy->check_command) {
7476 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7477 curproxy->id, "option external-check");
7478 cfgerr++;
7479 }
7480 }
7481
Simon Horman64e34162015-02-06 11:11:57 +09007482 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007483 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7484 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007485 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7486 "'email-alert myhostname', or 'email-alert to' "
7487 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007488 "to be present).\n",
7489 proxy_type_str(curproxy), curproxy->id);
7490 err_code |= ERR_WARN;
7491 free_email_alert(curproxy);
7492 }
7493 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007494 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007495 }
7496
Simon Horman98637e52014-06-20 12:30:16 +09007497 if (curproxy->check_command) {
7498 int clear = 0;
7499 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7500 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7501 "external-check command", proxy_type_str(curproxy), curproxy->id);
7502 err_code |= ERR_WARN;
7503 clear = 1;
7504 }
7505 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007506 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007507 curproxy->id, "external-check command");
7508 cfgerr++;
7509 }
7510 if (clear) {
7511 free(curproxy->check_command);
7512 curproxy->check_command = NULL;
7513 }
7514 }
7515
7516 if (curproxy->check_path) {
7517 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7518 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7519 "external-check path", proxy_type_str(curproxy), curproxy->id);
7520 err_code |= ERR_WARN;
7521 free(curproxy->check_path);
7522 curproxy->check_path = NULL;
7523 }
7524 }
7525
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007526 /* if a default backend was specified, let's find it */
7527 if (curproxy->defbe.name) {
7528 struct proxy *target;
7529
Willy Tarreauafb39922015-05-26 12:04:09 +02007530 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007531 if (!target) {
7532 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7533 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007534 cfgerr++;
7535 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007536 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7537 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007538 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007539 } else if (target->mode != curproxy->mode &&
7540 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7541
7542 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7543 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7544 curproxy->conf.file, curproxy->conf.line,
7545 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7546 target->conf.file, target->conf.line);
7547 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007548 } else {
7549 free(curproxy->defbe.name);
7550 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007551
7552 /* Emit a warning if this proxy also has some servers */
7553 if (curproxy->srv) {
7554 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7555 curproxy->id);
7556 err_code |= ERR_WARN;
7557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007558 }
7559 }
7560
Willy Tarreau55ea7572007-06-17 19:56:27 +02007561 /* find the target proxy for 'use_backend' rules */
7562 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007563 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007564 struct logformat_node *node;
7565 char *pxname;
7566
7567 /* Try to parse the string as a log format expression. If the result
7568 * of the parsing is only one entry containing a simple string, then
7569 * it's a standard string corresponding to a static rule, thus the
7570 * parsing is cancelled and be.name is restored to be resolved.
7571 */
7572 pxname = rule->be.name;
7573 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007574 curproxy->conf.args.ctx = ARGC_UBK;
7575 curproxy->conf.args.file = rule->file;
7576 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007577 err = NULL;
7578 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7579 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7580 rule->file, rule->line, pxname, err);
7581 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007582 cfgerr++;
7583 continue;
7584 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007585 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7586
7587 if (!LIST_ISEMPTY(&rule->be.expr)) {
7588 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7589 rule->dynamic = 1;
7590 free(pxname);
7591 continue;
7592 }
7593 /* simple string: free the expression and fall back to static rule */
7594 free(node->arg);
7595 free(node);
7596 }
7597
7598 rule->dynamic = 0;
7599 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007600
Willy Tarreauafb39922015-05-26 12:04:09 +02007601 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007602 if (!target) {
7603 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7604 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007605 cfgerr++;
7606 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007607 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7608 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007609 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007610 } else if (target->mode != curproxy->mode &&
7611 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7612
7613 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7614 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7615 curproxy->conf.file, curproxy->conf.line,
7616 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7617 target->conf.file, target->conf.line);
7618 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007619 } else {
7620 free((void *)rule->be.name);
7621 rule->be.backend = target;
7622 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007623 }
7624
Willy Tarreau64ab6072014-09-16 12:17:36 +02007625 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007626 list_for_each_entry(srule, &curproxy->server_rules, list) {
7627 struct server *target = findserver(curproxy, srule->srv.name);
7628
7629 if (!target) {
7630 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7631 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7632 cfgerr++;
7633 continue;
7634 }
7635 free((void *)srule->srv.name);
7636 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007637 }
7638
Emeric Brunb982a3d2010-01-04 15:45:53 +01007639 /* find the target table for 'stick' rules */
7640 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7641 struct proxy *target;
7642
Emeric Brun1d33b292010-01-04 15:47:17 +01007643 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7644 if (mrule->flags & STK_IS_STORE)
7645 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7646
Emeric Brunb982a3d2010-01-04 15:45:53 +01007647 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007648 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007649 else
7650 target = curproxy;
7651
7652 if (!target) {
7653 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7654 curproxy->id, mrule->table.name);
7655 cfgerr++;
7656 }
7657 else if (target->table.size == 0) {
7658 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7659 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7660 cfgerr++;
7661 }
Willy Tarreau12785782012-04-27 21:37:17 +02007662 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7663 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007664 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7665 cfgerr++;
7666 }
7667 else {
7668 free((void *)mrule->table.name);
7669 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007670 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007671 }
7672 }
7673
7674 /* find the target table for 'store response' rules */
7675 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7676 struct proxy *target;
7677
Emeric Brun1d33b292010-01-04 15:47:17 +01007678 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7679
Emeric Brunb982a3d2010-01-04 15:45:53 +01007680 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007681 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007682 else
7683 target = curproxy;
7684
7685 if (!target) {
7686 Alert("Proxy '%s': unable to find store table '%s'.\n",
7687 curproxy->id, mrule->table.name);
7688 cfgerr++;
7689 }
7690 else if (target->table.size == 0) {
7691 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7692 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7693 cfgerr++;
7694 }
Willy Tarreau12785782012-04-27 21:37:17 +02007695 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7696 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007697 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7698 cfgerr++;
7699 }
7700 else {
7701 free((void *)mrule->table.name);
7702 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007703 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007704 }
7705 }
7706
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007707 /* find the target table for 'tcp-request' layer 4 rules */
7708 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7709 struct proxy *target;
7710
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007711 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007712 continue;
7713
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007714 if (trule->arg.trk_ctr.table.n)
7715 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007716 else
7717 target = curproxy;
7718
7719 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007720 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007721 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007722 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007723 cfgerr++;
7724 }
7725 else if (target->table.size == 0) {
7726 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007727 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007728 cfgerr++;
7729 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007730 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007731 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007732 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007733 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007734 cfgerr++;
7735 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007736 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007737 free(trule->arg.trk_ctr.table.n);
7738 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007739 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007740 * to pass a list of counters to track and allocate them right here using
7741 * stktable_alloc_data_type().
7742 */
7743 }
7744 }
7745
Willy Tarreau620408f2016-10-21 16:37:51 +02007746 /* find the target table for 'tcp-request' layer 5 rules */
7747 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7748 struct proxy *target;
7749
7750 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7751 continue;
7752
7753 if (trule->arg.trk_ctr.table.n)
7754 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7755 else
7756 target = curproxy;
7757
7758 if (!target) {
7759 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7760 curproxy->id, trule->arg.trk_ctr.table.n,
7761 tcp_trk_idx(trule->action));
7762 cfgerr++;
7763 }
7764 else if (target->table.size == 0) {
7765 Alert("Proxy '%s': table '%s' used but not configured.\n",
7766 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7767 cfgerr++;
7768 }
7769 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7770 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7771 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7772 tcp_trk_idx(trule->action));
7773 cfgerr++;
7774 }
7775 else {
7776 free(trule->arg.trk_ctr.table.n);
7777 trule->arg.trk_ctr.table.t = &target->table;
7778 /* Note: if we decide to enhance the track-sc syntax, we may be able
7779 * to pass a list of counters to track and allocate them right here using
7780 * stktable_alloc_data_type().
7781 */
7782 }
7783 }
7784
Willy Tarreaud1f96522010-08-03 19:34:32 +02007785 /* find the target table for 'tcp-request' layer 6 rules */
7786 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7787 struct proxy *target;
7788
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007789 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007790 continue;
7791
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007792 if (trule->arg.trk_ctr.table.n)
7793 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007794 else
7795 target = curproxy;
7796
7797 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007798 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007799 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007800 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007801 cfgerr++;
7802 }
7803 else if (target->table.size == 0) {
7804 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007805 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007806 cfgerr++;
7807 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007808 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007809 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007810 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007811 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007812 cfgerr++;
7813 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007814 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007815 free(trule->arg.trk_ctr.table.n);
7816 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007817 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007818 * to pass a list of counters to track and allocate them right here using
7819 * stktable_alloc_data_type().
7820 */
7821 }
7822 }
7823
Baptiste Assmanne9544932015-11-03 23:31:35 +01007824 /* parse http-request capture rules to ensure id really exists */
7825 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7826 if (hrqrule->action != ACT_CUSTOM ||
7827 hrqrule->action_ptr != http_action_req_capture_by_id)
7828 continue;
7829
7830 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7831 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7832 curproxy->id, hrqrule->arg.capid.idx);
7833 cfgerr++;
7834 }
7835 }
7836
7837 /* parse http-response capture rules to ensure id really exists */
7838 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7839 if (hrqrule->action != ACT_CUSTOM ||
7840 hrqrule->action_ptr != http_action_res_capture_by_id)
7841 continue;
7842
7843 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7844 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7845 curproxy->id, hrqrule->arg.capid.idx);
7846 cfgerr++;
7847 }
7848 }
7849
Willy Tarreau09448f72014-06-25 18:12:15 +02007850 /* find the target table for 'http-request' layer 7 rules */
7851 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7852 struct proxy *target;
7853
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007854 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007855 continue;
7856
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007857 if (hrqrule->arg.trk_ctr.table.n)
7858 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007859 else
7860 target = curproxy;
7861
7862 if (!target) {
7863 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007864 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007865 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007866 cfgerr++;
7867 }
7868 else if (target->table.size == 0) {
7869 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007870 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007871 cfgerr++;
7872 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007873 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007874 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007875 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007876 http_trk_idx(hrqrule->action));
7877 cfgerr++;
7878 }
7879 else {
7880 free(hrqrule->arg.trk_ctr.table.n);
7881 hrqrule->arg.trk_ctr.table.t = &target->table;
7882 /* Note: if we decide to enhance the track-sc syntax, we may be able
7883 * to pass a list of counters to track and allocate them right here using
7884 * stktable_alloc_data_type().
7885 */
7886 }
7887 }
7888
7889 /* find the target table for 'http-response' layer 7 rules */
7890 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7891 struct proxy *target;
7892
7893 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7894 continue;
7895
7896 if (hrqrule->arg.trk_ctr.table.n)
7897 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7898 else
7899 target = curproxy;
7900
7901 if (!target) {
7902 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7903 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7904 http_trk_idx(hrqrule->action));
7905 cfgerr++;
7906 }
7907 else if (target->table.size == 0) {
7908 Alert("Proxy '%s': table '%s' used but not configured.\n",
7909 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
7910 cfgerr++;
7911 }
7912 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
7913 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7914 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
7915 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007916 cfgerr++;
7917 }
7918 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007919 free(hrqrule->arg.trk_ctr.table.n);
7920 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007921 /* Note: if we decide to enhance the track-sc syntax, we may be able
7922 * to pass a list of counters to track and allocate them right here using
7923 * stktable_alloc_data_type().
7924 */
7925 }
7926 }
7927
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007928 /* move any "block" rules at the beginning of the http-request rules */
7929 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7930 /* insert block_rules into http_req_rules at the beginning */
7931 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7932 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7933 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7934 curproxy->http_req_rules.n = curproxy->block_rules.n;
7935 LIST_INIT(&curproxy->block_rules);
7936 }
7937
Emeric Brun32da3c42010-09-23 18:39:19 +02007938 if (curproxy->table.peers.name) {
7939 struct peers *curpeers = peers;
7940
7941 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7942 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7943 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007944 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007945 break;
7946 }
7947 }
7948
7949 if (!curpeers) {
7950 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7951 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007952 free((void *)curproxy->table.peers.name);
7953 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007954 cfgerr++;
7955 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007956 else if (curpeers->state == PR_STSTOPPED) {
7957 /* silently disable this peers section */
7958 curproxy->table.peers.p = NULL;
7959 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007960 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007961 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7962 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007963 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007964 cfgerr++;
7965 }
7966 }
7967
Simon Horman9dc49962015-01-30 11:22:59 +09007968
7969 if (curproxy->email_alert.mailers.name) {
7970 struct mailers *curmailers = mailers;
7971
7972 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7973 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7974 free(curproxy->email_alert.mailers.name);
7975 curproxy->email_alert.mailers.m = curmailers;
7976 curmailers->users++;
7977 break;
7978 }
7979 }
7980
7981 if (!curmailers) {
7982 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7983 curproxy->id, curproxy->email_alert.mailers.name);
7984 free_email_alert(curproxy);
7985 cfgerr++;
7986 }
7987 }
7988
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007989 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007990 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007991 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7992 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7993 "proxy", curproxy->id);
7994 cfgerr++;
7995 goto out_uri_auth_compat;
7996 }
7997
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007998 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007999 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008000 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008001 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008002
Willy Tarreau95fa4692010-02-01 13:05:50 +01008003 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8004 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008005
8006 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008007 uri_auth_compat_req[i++] = "realm";
8008 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8009 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008010
Willy Tarreau95fa4692010-02-01 13:05:50 +01008011 uri_auth_compat_req[i++] = "unless";
8012 uri_auth_compat_req[i++] = "{";
8013 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8014 uri_auth_compat_req[i++] = "}";
8015 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008016
Willy Tarreauff011f22011-01-06 17:51:27 +01008017 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8018 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008019 cfgerr++;
8020 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008021 }
8022
Willy Tarreauff011f22011-01-06 17:51:27 +01008023 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008024
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008025 if (curproxy->uri_auth->auth_realm) {
8026 free(curproxy->uri_auth->auth_realm);
8027 curproxy->uri_auth->auth_realm = NULL;
8028 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008029
8030 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008031 }
8032out_uri_auth_compat:
8033
Dragan Dosen43885c72015-10-01 13:18:13 +02008034 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008035 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008036 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8037 if (!curproxy->conf.logformat_sd_string) {
8038 /* set the default logformat_sd_string */
8039 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8040 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008041 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008042 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008043 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008044
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008045 /* compile the log format */
8046 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008047 if (curproxy->conf.logformat_string != default_http_log_format &&
8048 curproxy->conf.logformat_string != default_tcp_log_format &&
8049 curproxy->conf.logformat_string != clf_http_log_format)
8050 free(curproxy->conf.logformat_string);
8051 curproxy->conf.logformat_string = NULL;
8052 free(curproxy->conf.lfs_file);
8053 curproxy->conf.lfs_file = NULL;
8054 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008055
8056 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8057 free(curproxy->conf.logformat_sd_string);
8058 curproxy->conf.logformat_sd_string = NULL;
8059 free(curproxy->conf.lfsd_file);
8060 curproxy->conf.lfsd_file = NULL;
8061 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008062 }
8063
Willy Tarreau62a61232013-04-12 18:13:46 +02008064 if (curproxy->conf.logformat_string) {
8065 curproxy->conf.args.ctx = ARGC_LOG;
8066 curproxy->conf.args.file = curproxy->conf.lfs_file;
8067 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008068 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008069 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008070 SMP_VAL_FE_LOG_END, &err)) {
8071 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8072 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8073 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008074 cfgerr++;
8075 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008076 curproxy->conf.args.file = NULL;
8077 curproxy->conf.args.line = 0;
8078 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008079
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008080 if (curproxy->conf.logformat_sd_string) {
8081 curproxy->conf.args.ctx = ARGC_LOGSD;
8082 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8083 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008084 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008085 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 +01008086 SMP_VAL_FE_LOG_END, &err)) {
8087 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8088 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8089 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008090 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008091 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8092 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8093 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8094 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008095 cfgerr++;
8096 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008097 curproxy->conf.args.file = NULL;
8098 curproxy->conf.args.line = 0;
8099 }
8100
Willy Tarreau62a61232013-04-12 18:13:46 +02008101 if (curproxy->conf.uniqueid_format_string) {
8102 curproxy->conf.args.ctx = ARGC_UIF;
8103 curproxy->conf.args.file = curproxy->conf.uif_file;
8104 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008105 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008106 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 +01008107 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8108 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8109 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8110 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008111 cfgerr++;
8112 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008113 curproxy->conf.args.file = NULL;
8114 curproxy->conf.args.line = 0;
8115 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008116
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008117 /* only now we can check if some args remain unresolved.
8118 * This must be done after the users and groups resolution.
8119 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008120 cfgerr += smp_resolve_args(curproxy);
8121 if (!cfgerr)
8122 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008123
Willy Tarreau2738a142006-07-08 17:28:09 +02008124 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008125 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008126 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008127 (!curproxy->timeout.connect ||
8128 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008129 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008130 " | While not properly invalid, you will certainly encounter various problems\n"
8131 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008132 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008133 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008134 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008135 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008136
Willy Tarreau1fa31262007-12-03 00:36:16 +01008137 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8138 * We must still support older configurations, so let's find out whether those
8139 * parameters have been set or must be copied from contimeouts.
8140 */
8141 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008142 if (!curproxy->timeout.tarpit ||
8143 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008144 /* tarpit timeout not set. We search in the following order:
8145 * default.tarpit, curr.connect, default.connect.
8146 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008147 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008148 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008149 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008150 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008151 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008152 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008153 }
8154 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008155 (!curproxy->timeout.queue ||
8156 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008157 /* queue timeout not set. We search in the following order:
8158 * default.queue, curr.connect, default.connect.
8159 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008160 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008161 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008162 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008163 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008164 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008165 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008166 }
8167 }
8168
Willy Tarreau1620ec32011-08-06 17:05:02 +02008169 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008170 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008171 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008172 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008173 }
8174
Willy Tarreau215663d2014-06-13 18:30:23 +02008175 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8176 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8177 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8178 proxy_type_str(curproxy), curproxy->id);
8179 err_code |= ERR_WARN;
8180 }
8181
Willy Tarreau193b8c62012-11-22 00:17:38 +01008182 /* ensure that cookie capture length is not too large */
8183 if (curproxy->capture_len >= global.tune.cookie_len) {
8184 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8185 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8186 err_code |= ERR_WARN;
8187 curproxy->capture_len = global.tune.cookie_len - 1;
8188 }
8189
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008190 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008191 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008192 curproxy->req_cap_pool = create_pool("ptrcap",
8193 curproxy->nb_req_cap * sizeof(char *),
8194 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008195 }
8196
8197 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008198 curproxy->rsp_cap_pool = create_pool("ptrcap",
8199 curproxy->nb_rsp_cap * sizeof(char *),
8200 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008201 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008202
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008203 switch (curproxy->load_server_state_from_file) {
8204 case PR_SRV_STATE_FILE_UNSPEC:
8205 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8206 break;
8207 case PR_SRV_STATE_FILE_GLOBAL:
8208 if (!global.server_state_file) {
8209 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",
8210 curproxy->id);
8211 err_code |= ERR_WARN;
8212 }
8213 break;
8214 }
8215
Willy Tarreaubaaee002006-06-26 02:48:02 +02008216 /* first, we will invert the servers list order */
8217 newsrv = NULL;
8218 while (curproxy->srv) {
8219 struct server *next;
8220
8221 next = curproxy->srv->next;
8222 curproxy->srv->next = newsrv;
8223 newsrv = curproxy->srv;
8224 if (!next)
8225 break;
8226 curproxy->srv = next;
8227 }
8228
Willy Tarreau17edc812014-01-03 12:14:34 +01008229 /* Check that no server name conflicts. This causes trouble in the stats.
8230 * We only emit a warning for the first conflict affecting each server,
8231 * in order to avoid combinatory explosion if all servers have the same
8232 * name. We do that only for servers which do not have an explicit ID,
8233 * because these IDs were made also for distinguishing them and we don't
8234 * want to annoy people who correctly manage them.
8235 */
8236 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8237 struct server *other_srv;
8238
8239 if (newsrv->puid)
8240 continue;
8241
8242 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8243 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8244 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8245 newsrv->conf.file, newsrv->conf.line,
8246 proxy_type_str(curproxy), curproxy->id,
8247 newsrv->id, other_srv->conf.line);
8248 break;
8249 }
8250 }
8251 }
8252
Willy Tarreaudd701652010-05-25 23:03:02 +02008253 /* assign automatic UIDs to servers which don't have one yet */
8254 next_id = 1;
8255 newsrv = curproxy->srv;
8256 while (newsrv != NULL) {
8257 if (!newsrv->puid) {
8258 /* server ID not set, use automatic numbering with first
8259 * spare entry starting with next_svid.
8260 */
8261 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8262 newsrv->conf.id.key = newsrv->puid = next_id;
8263 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8264 }
8265 next_id++;
8266 newsrv = newsrv->next;
8267 }
8268
Willy Tarreau20697042007-11-15 23:26:18 +01008269 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008270 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008271
Willy Tarreau62c3be22012-01-20 13:12:32 +01008272 /*
8273 * If this server supports a maxconn parameter, it needs a dedicated
8274 * tasks to fill the emptied slots when a connection leaves.
8275 * Also, resolve deferred tracking dependency if needed.
8276 */
8277 newsrv = curproxy->srv;
8278 while (newsrv != NULL) {
8279 if (newsrv->minconn > newsrv->maxconn) {
8280 /* Only 'minconn' was specified, or it was higher than or equal
8281 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8282 * this will avoid further useless expensive computations.
8283 */
8284 newsrv->maxconn = newsrv->minconn;
8285 } else if (newsrv->maxconn && !newsrv->minconn) {
8286 /* minconn was not specified, so we set it to maxconn */
8287 newsrv->minconn = newsrv->maxconn;
8288 }
8289
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008290#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008291 if (newsrv->use_ssl || newsrv->check.use_ssl)
8292 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008293#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008294
Willy Tarreau2f075e92013-12-03 11:11:34 +01008295 /* set the check type on the server */
8296 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8297
Willy Tarreau62c3be22012-01-20 13:12:32 +01008298 if (newsrv->trackit) {
8299 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008300 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008301 char *pname, *sname;
8302
8303 pname = newsrv->trackit;
8304 sname = strrchr(pname, '/');
8305
8306 if (sname)
8307 *sname++ = '\0';
8308 else {
8309 sname = pname;
8310 pname = NULL;
8311 }
8312
8313 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008314 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008315 if (!px) {
8316 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8317 proxy_type_str(curproxy), curproxy->id,
8318 newsrv->id, pname);
8319 cfgerr++;
8320 goto next_srv;
8321 }
8322 } else
8323 px = curproxy;
8324
8325 srv = findserver(px, sname);
8326 if (!srv) {
8327 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8328 proxy_type_str(curproxy), curproxy->id,
8329 newsrv->id, sname);
8330 cfgerr++;
8331 goto next_srv;
8332 }
8333
Willy Tarreau32091232014-05-16 13:52:00 +02008334 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8335 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8336 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008337 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008338 "tracking as it does not have any check nor agent enabled.\n",
8339 proxy_type_str(curproxy), curproxy->id,
8340 newsrv->id, px->id, srv->id);
8341 cfgerr++;
8342 goto next_srv;
8343 }
8344
8345 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8346
8347 if (loop) {
8348 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8349 "belongs to a tracking chain looping back to %s/%s.\n",
8350 proxy_type_str(curproxy), curproxy->id,
8351 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008352 cfgerr++;
8353 goto next_srv;
8354 }
8355
8356 if (curproxy != px &&
8357 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8358 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8359 "tracking: disable-on-404 option inconsistency.\n",
8360 proxy_type_str(curproxy), curproxy->id,
8361 newsrv->id, px->id, srv->id);
8362 cfgerr++;
8363 goto next_srv;
8364 }
8365
Willy Tarreau62c3be22012-01-20 13:12:32 +01008366 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008367 newsrv->tracknext = srv->trackers;
8368 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008369
8370 free(newsrv->trackit);
8371 newsrv->trackit = NULL;
8372 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008373
8374 /*
8375 * resolve server's resolvers name and update the resolvers pointer
8376 * accordingly
8377 */
8378 if (newsrv->resolvers_id) {
8379 struct dns_resolvers *curr_resolvers;
8380 int found;
8381
8382 found = 0;
8383 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8384 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8385 found = 1;
8386 break;
8387 }
8388 }
8389
8390 if (!found) {
8391 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8392 proxy_type_str(curproxy), curproxy->id,
8393 newsrv->id, newsrv->resolvers_id);
8394 cfgerr++;
8395 } else {
8396 free(newsrv->resolvers_id);
8397 newsrv->resolvers_id = NULL;
8398 if (newsrv->resolution)
8399 newsrv->resolution->resolvers = curr_resolvers;
8400 }
8401 }
8402 else {
8403 /* if no resolvers section associated to this server
8404 * we can clean up the associated resolution structure
8405 */
8406 if (newsrv->resolution) {
8407 free(newsrv->resolution->hostname_dn);
8408 newsrv->resolution->hostname_dn = NULL;
8409 free(newsrv->resolution);
8410 newsrv->resolution = NULL;
8411 }
8412 }
8413
Willy Tarreau62c3be22012-01-20 13:12:32 +01008414 next_srv:
8415 newsrv = newsrv->next;
8416 }
8417
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008418 /* We have to initialize the server lookup mechanism depending
8419 * on what LB algorithm was choosen.
8420 */
8421
8422 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8423 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8424 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008425 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8426 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8427 init_server_map(curproxy);
8428 } else {
8429 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8430 fwrr_init_server_groups(curproxy);
8431 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008432 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008433
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008434 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008435 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8436 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8437 fwlc_init_server_tree(curproxy);
8438 } else {
8439 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8440 fas_init_server_tree(curproxy);
8441 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008442 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008443
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008444 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008445 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8446 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8447 chash_init_server_tree(curproxy);
8448 } else {
8449 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8450 init_server_map(curproxy);
8451 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008452 break;
8453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008454
8455 if (curproxy->options & PR_O_LOGASAP)
8456 curproxy->to_log &= ~LW_BYTES;
8457
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008458 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008459 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8460 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008461 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8462 proxy_type_str(curproxy), curproxy->id);
8463 err_code |= ERR_WARN;
8464 }
8465
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008466 if (curproxy->mode != PR_MODE_HTTP) {
8467 int optnum;
8468
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008469 if (curproxy->uri_auth) {
8470 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8471 proxy_type_str(curproxy), curproxy->id);
8472 err_code |= ERR_WARN;
8473 curproxy->uri_auth = NULL;
8474 }
8475
Willy Tarreau87cf5142011-08-19 22:57:24 +02008476 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008477 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8478 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8479 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008480 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008481 }
8482
8483 if (curproxy->options & PR_O_ORGTO) {
8484 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8485 "originalto", proxy_type_str(curproxy), curproxy->id);
8486 err_code |= ERR_WARN;
8487 curproxy->options &= ~PR_O_ORGTO;
8488 }
8489
8490 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8491 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8492 (curproxy->cap & cfg_opts[optnum].cap) &&
8493 (curproxy->options & cfg_opts[optnum].val)) {
8494 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8495 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8496 err_code |= ERR_WARN;
8497 curproxy->options &= ~cfg_opts[optnum].val;
8498 }
8499 }
8500
8501 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8502 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8503 (curproxy->cap & cfg_opts2[optnum].cap) &&
8504 (curproxy->options2 & cfg_opts2[optnum].val)) {
8505 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8506 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8507 err_code |= ERR_WARN;
8508 curproxy->options2 &= ~cfg_opts2[optnum].val;
8509 }
8510 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008511
Willy Tarreau29fbe512015-08-20 19:35:14 +02008512#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008513 if (curproxy->conn_src.bind_hdr_occ) {
8514 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008515 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008516 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008517 err_code |= ERR_WARN;
8518 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008519#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008520 }
8521
Willy Tarreaubaaee002006-06-26 02:48:02 +02008522 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008523 * ensure that we're not cross-dressing a TCP server into HTTP.
8524 */
8525 newsrv = curproxy->srv;
8526 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008527 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008528 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8529 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008530 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008531 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008532
Willy Tarreau0cec3312011-10-31 13:49:26 +01008533 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8534 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8535 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8536 err_code |= ERR_WARN;
8537 }
8538
Willy Tarreauc93cd162014-05-13 15:54:22 +02008539 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008540 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8541 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8542 err_code |= ERR_WARN;
8543 }
8544
Willy Tarreau29fbe512015-08-20 19:35:14 +02008545#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008546 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8547 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008548 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 +01008549 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008550 err_code |= ERR_WARN;
8551 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008552#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008553 newsrv = newsrv->next;
8554 }
8555
Willy Tarreaue42bd962014-09-16 16:21:19 +02008556 /* check if we have a frontend with "tcp-request content" looking at L7
8557 * with no inspect-delay
8558 */
8559 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8560 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008561 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008562 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008563 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008564 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008565 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008566 break;
8567 }
8568
8569 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8570 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8571 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8572 " This means that these rules will randomly find their contents. This can be fixed by"
8573 " setting the tcp-request inspect-delay.\n",
8574 proxy_type_str(curproxy), curproxy->id);
8575 err_code |= ERR_WARN;
8576 }
8577 }
8578
Christopher Fauletd7c91962015-04-30 11:48:27 +02008579 /* Check filter configuration, if any */
8580 cfgerr += flt_check(curproxy);
8581
Willy Tarreauc1a21672009-08-16 22:37:44 +02008582 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008583 if (!curproxy->accept)
8584 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008585
Willy Tarreauc1a21672009-08-16 22:37:44 +02008586 if (curproxy->tcp_req.inspect_delay ||
8587 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008588 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008589
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008590 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008591 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008592 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008593 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008594
8595 /* both TCP and HTTP must check switching rules */
8596 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008597
8598 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008599 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008600 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8601 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008602 if (curproxy->mode == PR_MODE_HTTP) {
8603 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8604 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8605 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008606 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008607 }
8608
8609 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008610 if (curproxy->tcp_req.inspect_delay ||
8611 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8612 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8613
Emeric Brun97679e72010-09-23 17:56:44 +02008614 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8615 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8616
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008617 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008618 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008619 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008620 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008621
8622 /* If the backend does requires RDP cookie persistence, we have to
8623 * enable the corresponding analyser.
8624 */
8625 if (curproxy->options2 & PR_O2_RDPC_PRST)
8626 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008627
8628 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008629 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008630 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8631 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008632 if (curproxy->mode == PR_MODE_HTTP) {
8633 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8634 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8635 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008636 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008637 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008638 }
8639
8640 /***********************************************************/
8641 /* At this point, target names have already been resolved. */
8642 /***********************************************************/
8643
8644 /* Check multi-process mode compatibility */
8645
8646 if (global.nbproc > 1 && global.stats_fe) {
8647 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8648 unsigned long mask;
8649
8650 mask = nbits(global.nbproc);
8651 if (global.stats_fe->bind_proc)
8652 mask &= global.stats_fe->bind_proc;
8653
8654 if (bind_conf->bind_proc)
8655 mask &= bind_conf->bind_proc;
8656
8657 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008658 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008659 break;
8660 }
8661 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8662 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");
8663 }
8664 }
8665
8666 /* Make each frontend inherit bind-process from its listeners when not specified. */
8667 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8668 if (curproxy->bind_proc)
8669 continue;
8670
8671 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8672 unsigned long mask;
8673
Willy Tarreaue428b082015-05-04 21:57:58 +02008674 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008675 curproxy->bind_proc |= mask;
8676 }
8677
8678 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008679 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008680 }
8681
8682 if (global.stats_fe) {
8683 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8684 unsigned long mask;
8685
Cyril Bonté06181952016-02-24 00:14:54 +01008686 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008687 global.stats_fe->bind_proc |= mask;
8688 }
8689 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008690 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008691 }
8692
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008693 /* propagate bindings from frontends to backends. Don't do it if there
8694 * are any fatal errors as we must not call it with unresolved proxies.
8695 */
8696 if (!cfgerr) {
8697 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8698 if (curproxy->cap & PR_CAP_FE)
8699 propagate_processes(curproxy, NULL);
8700 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008701 }
8702
8703 /* Bind each unbound backend to all processes when not specified. */
8704 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8705 if (curproxy->bind_proc)
8706 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008707 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008708 }
8709
8710 /*******************************************************/
8711 /* At this step, all proxies have a non-null bind_proc */
8712 /*******************************************************/
8713
8714 /* perform the final checks before creating tasks */
8715
8716 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8717 struct listener *listener;
8718 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008719
Emeric Brunc52962f2012-11-15 18:28:02 +01008720#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008721 /* Configure SSL for each bind line.
8722 * Note: if configuration fails at some point, the ->ctx member
8723 * remains NULL so that listeners can later detach.
8724 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008725 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008726 int alloc_ctx;
8727
Emeric Brunc52962f2012-11-15 18:28:02 +01008728 if (!bind_conf->is_ssl) {
8729 if (bind_conf->default_ctx) {
8730 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8731 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8732 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008733 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008734 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008735 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008736 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008737 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008738 cfgerr++;
8739 continue;
8740 }
8741
Emeric Brun8dc60392014-05-09 13:52:00 +02008742 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008743 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008744 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8745 Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
8746 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008747 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008748 cfgerr++;
8749 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008750 }
8751
Emeric Brunfc0421f2012-09-07 17:30:07 +02008752 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008753 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008754
8755 /* initialize CA variables if the certificates generation is enabled */
8756 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008757 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008758#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008759
Willy Tarreaue6b98942007-10-29 01:09:36 +01008760 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008761 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008762 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008763 int nbproc;
8764
8765 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008766 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008767 nbits(global.nbproc));
8768
8769 if (!nbproc) /* no intersection between listener and frontend */
8770 nbproc = 1;
8771
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008772 if (!listener->luid) {
8773 /* listener ID not set, use automatic numbering with first
8774 * spare entry starting with next_luid.
8775 */
8776 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8777 listener->conf.id.key = listener->luid = next_id;
8778 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008779 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008780 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008781
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008782 /* enable separate counters */
8783 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008784 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008785 if (!listener->name)
8786 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008787 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008788
Willy Tarreaue6b98942007-10-29 01:09:36 +01008789 if (curproxy->options & PR_O_TCP_NOLING)
8790 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008791 if (!listener->maxconn)
8792 listener->maxconn = curproxy->maxconn;
8793 if (!listener->backlog)
8794 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008795 if (!listener->maxaccept)
8796 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8797
8798 /* we want to have an optimal behaviour on single process mode to
8799 * maximize the work at once, but in multi-process we want to keep
8800 * some fairness between processes, so we target half of the max
8801 * number of events to be balanced over all the processes the proxy
8802 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8803 * used to disable the limit.
8804 */
8805 if (listener->maxaccept > 0) {
8806 if (nbproc > 1)
8807 listener->maxaccept = (listener->maxaccept + 1) / 2;
8808 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8809 }
8810
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008811 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008812 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008813 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008814 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008815
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008816 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008817 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008818
Willy Tarreau620408f2016-10-21 16:37:51 +02008819 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8820 listener->options |= LI_O_TCP_L5_RULES;
8821
Willy Tarreaude3041d2010-05-31 10:56:17 +02008822 if (curproxy->mon_mask.s_addr)
8823 listener->options |= LI_O_CHK_MONNET;
8824
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008825 /* smart accept mode is automatic in HTTP mode */
8826 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008827 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008828 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8829 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008830 }
8831
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008832 /* Release unused SSL configs */
8833 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8834 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008835 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008836#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008837 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008838 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008839 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008840 free(bind_conf->ca_sign_file);
8841 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008842 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008843 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008844 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008845 if(bind_conf->keys_ref) {
8846 free(bind_conf->keys_ref->filename);
8847 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02008848 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008849 free(bind_conf->keys_ref);
8850 }
Willy Tarreau94ff03a2016-12-22 17:57:46 +01008851 bind_conf->keys_ref = NULL;
8852 bind_conf->crl_file = NULL;
8853 bind_conf->ecdhe = NULL;
8854 bind_conf->ciphers = NULL;
8855 bind_conf->ca_sign_pass = NULL;
8856 bind_conf->ca_sign_file = NULL;
8857 bind_conf->ca_file = NULL;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008858#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008859 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008860
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008861 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008862 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008863 int count, maxproc = 0;
8864
8865 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008866 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008867 if (count > maxproc)
8868 maxproc = count;
8869 }
8870 /* backends have 0, frontends have 1 or more */
8871 if (maxproc != 1)
8872 Warning("Proxy '%s': in multi-process mode, stats will be"
8873 " limited to process assigned to the current request.\n",
8874 curproxy->id);
8875
Willy Tarreau102df612014-05-07 23:56:38 +02008876 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8877 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8878 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008879 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008880 }
Willy Tarreau102df612014-05-07 23:56:38 +02008881 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8882 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8883 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008884 }
8885 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008886
8887 /* create the task associated with the proxy */
8888 curproxy->task = task_new();
8889 if (curproxy->task) {
8890 curproxy->task->context = curproxy;
8891 curproxy->task->process = manage_proxy;
8892 /* no need to queue, it will be done automatically if some
8893 * listener gets limited.
8894 */
8895 curproxy->task->expire = TICK_ETERNITY;
8896 } else {
8897 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8898 curproxy->id);
8899 cfgerr++;
8900 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008901 }
8902
Willy Tarreaufbb78422011-06-05 15:38:35 +02008903 /* automatically compute fullconn if not set. We must not do it in the
8904 * loop above because cross-references are not yet fully resolved.
8905 */
8906 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8907 /* If <fullconn> is not set, let's set it to 10% of the sum of
8908 * the possible incoming frontend's maxconns.
8909 */
8910 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8911 struct proxy *fe;
8912 int total = 0;
8913
8914 /* sum up the number of maxconns of frontends which
8915 * reference this backend at least once or which are
8916 * the same one ('listen').
8917 */
8918 for (fe = proxy; fe; fe = fe->next) {
8919 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008920 int found = 0;
8921
8922 if (!(fe->cap & PR_CAP_FE))
8923 continue;
8924
8925 if (fe == curproxy) /* we're on a "listen" instance */
8926 found = 1;
8927
8928 if (fe->defbe.be == curproxy) /* "default_backend" */
8929 found = 1;
8930
8931 /* check if a "use_backend" rule matches */
8932 if (!found) {
8933 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008934 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008935 found = 1;
8936 break;
8937 }
8938 }
8939 }
8940
Willy Tarreaufbb78422011-06-05 15:38:35 +02008941 /* now we've checked all possible ways to reference a backend
8942 * from a frontend.
8943 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008944 if (!found)
8945 continue;
8946 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008947 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008948 /* we have the sum of the maxconns in <total>. We only
8949 * keep 10% of that sum to set the default fullconn, with
8950 * a hard minimum of 1 (to avoid a divide by zero).
8951 */
8952 curproxy->fullconn = (total + 9) / 10;
8953 if (!curproxy->fullconn)
8954 curproxy->fullconn = 1;
8955 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008956 }
8957
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008958 /*
8959 * Recount currently required checks.
8960 */
8961
8962 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8963 int optnum;
8964
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008965 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8966 if (curproxy->options & cfg_opts[optnum].val)
8967 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008968
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008969 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8970 if (curproxy->options2 & cfg_opts2[optnum].val)
8971 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008972 }
8973
Willy Tarreau0fca4832015-05-01 19:12:05 +02008974 /* compute the required process bindings for the peers */
8975 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8976 if (curproxy->table.peers.p)
8977 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8978
Willy Tarreau122541c2011-09-07 21:24:49 +02008979 if (peers) {
8980 struct peers *curpeers = peers, **last;
8981 struct peer *p, *pb;
8982
Willy Tarreau1e273012015-05-01 19:15:17 +02008983 /* Remove all peers sections which don't have a valid listener,
8984 * which are not used by any table, or which are bound to more
8985 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008986 */
8987 last = &peers;
8988 while (*last) {
8989 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008990
8991 if (curpeers->state == PR_STSTOPPED) {
8992 /* the "disabled" keyword was present */
8993 if (curpeers->peers_fe)
8994 stop_proxy(curpeers->peers_fe);
8995 curpeers->peers_fe = NULL;
8996 }
8997 else if (!curpeers->peers_fe) {
8998 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8999 curpeers->id, localpeer);
9000 }
David Carliere6c39412015-07-02 07:00:17 +00009001 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009002 /* either it's totally stopped or too much used */
9003 if (curpeers->peers_fe->bind_proc) {
9004 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009005 "running in different processes (%d different ones). "
9006 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009007 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009008 cfgerr++;
9009 }
9010 stop_proxy(curpeers->peers_fe);
9011 curpeers->peers_fe = NULL;
9012 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009013 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009014 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009015 last = &curpeers->next;
9016 continue;
9017 }
9018
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009019 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009020 p = curpeers->remote;
9021 while (p) {
9022 pb = p->next;
9023 free(p->id);
9024 free(p);
9025 p = pb;
9026 }
9027
9028 /* Destroy and unlink this curpeers section.
9029 * Note: curpeers is backed up into *last.
9030 */
9031 free(curpeers->id);
9032 curpeers = curpeers->next;
9033 free(*last);
9034 *last = curpeers;
9035 }
9036 }
9037
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009038 /* initialize stick-tables on backend capable proxies. This must not
9039 * be done earlier because the data size may be discovered while parsing
9040 * other proxies.
9041 */
9042 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9043 if (curproxy->state == PR_STSTOPPED)
9044 continue;
9045
9046 if (!stktable_init(&curproxy->table)) {
9047 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9048 cfgerr++;
9049 }
9050 }
9051
Simon Horman0d16a402015-01-30 11:22:58 +09009052 if (mailers) {
9053 struct mailers *curmailers = mailers, **last;
9054 struct mailer *m, *mb;
9055
9056 /* Remove all mailers sections which don't have a valid listener.
9057 * This can happen when a mailers section is never referenced.
9058 */
9059 last = &mailers;
9060 while (*last) {
9061 curmailers = *last;
9062 if (curmailers->users) {
9063 last = &curmailers->next;
9064 continue;
9065 }
9066
9067 Warning("Removing incomplete section 'mailers %s'.\n",
9068 curmailers->id);
9069
9070 m = curmailers->mailer_list;
9071 while (m) {
9072 mb = m->next;
9073 free(m->id);
9074 free(m);
9075 m = mb;
9076 }
9077
9078 /* Destroy and unlink this curmailers section.
9079 * Note: curmailers is backed up into *last.
9080 */
9081 free(curmailers->id);
9082 curmailers = curmailers->next;
9083 free(*last);
9084 *last = curmailers;
9085 }
9086 }
9087
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009088 /* Update server_state_file_name to backend name if backend is supposed to use
9089 * a server-state file locally defined and none has been provided */
9090 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9091 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9092 curproxy->server_state_file_name == NULL)
9093 curproxy->server_state_file_name = strdup(curproxy->id);
9094 }
9095
Willy Tarreau34eb6712011-10-24 18:15:04 +02009096 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009097 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009098 MEM_F_SHARED);
9099
Willy Tarreaubb925012009-07-23 13:36:36 +02009100 if (cfgerr > 0)
9101 err_code |= ERR_ALERT | ERR_FATAL;
9102 out:
9103 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009104}
9105
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009106/*
9107 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9108 * parsing sessions.
9109 */
9110void cfg_register_keywords(struct cfg_kw_list *kwl)
9111{
9112 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9113}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009114
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009115/*
9116 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9117 */
9118void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9119{
9120 LIST_DEL(&kwl->list);
9121 LIST_INIT(&kwl->list);
9122}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009123
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009124/* this function register new section in the haproxy configuration file.
9125 * <section_name> is the name of this new section and <section_parser>
9126 * is the called parser. If two section declaration have the same name,
9127 * only the first declared is used.
9128 */
9129int cfg_register_section(char *section_name,
9130 int (*section_parser)(const char *, int, char **, int))
9131{
9132 struct cfg_section *cs;
9133
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009134 list_for_each_entry(cs, &sections, list) {
9135 if (strcmp(cs->section_name, section_name) == 0) {
9136 Alert("register section '%s': already registered.\n", section_name);
9137 return 0;
9138 }
9139 }
9140
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009141 cs = calloc(1, sizeof(*cs));
9142 if (!cs) {
9143 Alert("register section '%s': out of memory.\n", section_name);
9144 return 0;
9145 }
9146
9147 cs->section_name = section_name;
9148 cs->section_parser = section_parser;
9149
9150 LIST_ADDQ(&sections, &cs->list);
9151
9152 return 1;
9153}
9154
Willy Tarreaubaaee002006-06-26 02:48:02 +02009155/*
David Carlier845efb52015-09-25 11:49:18 +01009156 * free all config section entries
9157 */
9158void cfg_unregister_sections(void)
9159{
9160 struct cfg_section *cs, *ics;
9161
9162 list_for_each_entry_safe(cs, ics, &sections, list) {
9163 LIST_DEL(&cs->list);
9164 free(cs);
9165 }
9166}
9167
Christopher Faulet7110b402016-10-26 11:09:44 +02009168void cfg_backup_sections(struct list *backup_sections)
9169{
9170 struct cfg_section *cs, *ics;
9171
9172 list_for_each_entry_safe(cs, ics, &sections, list) {
9173 LIST_DEL(&cs->list);
9174 LIST_ADDQ(backup_sections, &cs->list);
9175 }
9176}
9177
9178void cfg_restore_sections(struct list *backup_sections)
9179{
9180 struct cfg_section *cs, *ics;
9181
9182 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9183 LIST_DEL(&cs->list);
9184 LIST_ADDQ(&sections, &cs->list);
9185 }
9186}
9187
Willy Tarreau659fbf02016-05-26 17:55:28 +02009188__attribute__((constructor))
9189static void cfgparse_init(void)
9190{
9191 /* Register internal sections */
9192 cfg_register_section("listen", cfg_parse_listen);
9193 cfg_register_section("frontend", cfg_parse_listen);
9194 cfg_register_section("backend", cfg_parse_listen);
9195 cfg_register_section("defaults", cfg_parse_listen);
9196 cfg_register_section("global", cfg_parse_global);
9197 cfg_register_section("userlist", cfg_parse_users);
9198 cfg_register_section("peers", cfg_parse_peers);
9199 cfg_register_section("mailers", cfg_parse_mailers);
9200 cfg_register_section("namespace_list", cfg_parse_netns);
9201 cfg_register_section("resolvers", cfg_parse_resolvers);
9202}
9203
David Carlier845efb52015-09-25 11:49:18 +01009204/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009205 * Local variables:
9206 * c-indent-level: 8
9207 * c-basic-offset: 8
9208 * End:
9209 */