blob: 0ece4fdebf28d3c8015e49036badb2678f242076 [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);
300 l->frontend = curproxy;
301 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau40aa0702013-03-10 23:51:38 +0100303 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200304 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200305 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100306 l->state = LI_INIT;
307
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100308 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 tcpv4_add_listener(l);
311 }
Emeric Bruned760922010-10-22 17:59:25 +0200312 else if (ss.ss_family == AF_INET6) {
313 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
314 tcpv6_add_listener(l);
315 }
316 else {
Emeric Bruned760922010-10-22 17:59:25 +0200317 uxst_add_listener(l);
318 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200319
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200320 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100321 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322 } /* end for(port) */
323 } /* end while(next) */
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326 fail:
327 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200328 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200329}
330
William Lallemand6e62fb62015-04-28 16:55:23 +0200331/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100332 * Report an error in <msg> when there are too many arguments. This version is
333 * intended to be used by keyword parsers so that the message will be included
334 * into the general error message. The index is the current keyword in args.
335 * Return 0 if the number of argument is correct, otherwise build a message and
336 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
337 * message may also be null, it will simply not be produced (useful to check only).
338 * <msg> and <err_code> are only affected on error.
339 */
340int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
341{
342 int i;
343
344 if (!*args[index + maxarg + 1])
345 return 0;
346
347 if (msg) {
348 *msg = NULL;
349 memprintf(msg, "%s", args[0]);
350 for (i = 1; i <= index; i++)
351 memprintf(msg, "%s %s", *msg, args[i]);
352
353 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
354 }
355 if (err_code)
356 *err_code |= ERR_ALERT | ERR_FATAL;
357
358 return 1;
359}
360
361/*
362 * same as too_many_args_idx with a 0 index
363 */
364int too_many_args(int maxarg, char **args, char **msg, int *err_code)
365{
366 return too_many_args_idx(maxarg, 0, args, msg, err_code);
367}
368
369/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200370 * Report a fatal Alert when there is too much arguments
371 * The index is the current keyword in args
372 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
373 * Fill err_code with an ERR_ALERT and an ERR_FATAL
374 */
375int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
376{
377 char *kw = NULL;
378 int i;
379
380 if (!*args[index + maxarg + 1])
381 return 0;
382
383 memprintf(&kw, "%s", args[0]);
384 for (i = 1; i <= index; i++) {
385 memprintf(&kw, "%s %s", kw, args[i]);
386 }
387
388 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
389 free(kw);
390 *err_code |= ERR_ALERT | ERR_FATAL;
391 return 1;
392}
393
394/*
395 * same as alertif_too_many_args_idx with a 0 index
396 */
397int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
398{
399 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
400}
401
Willy Tarreau620408f2016-10-21 16:37:51 +0200402/* Report a warning if a rule is placed after a 'tcp-request session' rule.
403 * Return 1 if the warning has been emitted, otherwise 0.
404 */
405int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
406{
407 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
408 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
409 file, line, arg);
410 return 1;
411 }
412 return 0;
413}
414
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200415/* Report a warning if a rule is placed after a 'tcp-request content' rule.
416 * Return 1 if the warning has been emitted, otherwise 0.
417 */
418int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
419{
420 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
421 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
422 file, line, arg);
423 return 1;
424 }
425 return 0;
426}
427
Willy Tarreau61d18892009-03-31 10:49:21 +0200428/* Report a warning if a rule is placed after a 'block' rule.
429 * Return 1 if the warning has been emitted, otherwise 0.
430 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100431int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200432{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200433 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200434 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
435 file, line, arg);
436 return 1;
437 }
438 return 0;
439}
440
Willy Tarreau5002f572014-04-23 01:32:02 +0200441/* Report a warning if a rule is placed after an 'http_request' rule.
442 * Return 1 if the warning has been emitted, otherwise 0.
443 */
444int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
445{
446 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
447 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
448 file, line, arg);
449 return 1;
450 }
451 return 0;
452}
453
Willy Tarreau61d18892009-03-31 10:49:21 +0200454/* Report a warning if a rule is placed after a reqrewrite rule.
455 * Return 1 if the warning has been emitted, otherwise 0.
456 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100457int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200458{
459 if (proxy->req_exp) {
460 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
461 file, line, arg);
462 return 1;
463 }
464 return 0;
465}
466
467/* Report a warning if a rule is placed after a reqadd rule.
468 * Return 1 if the warning has been emitted, otherwise 0.
469 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100470int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200471{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100472 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200473 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
474 file, line, arg);
475 return 1;
476 }
477 return 0;
478}
479
480/* Report a warning if a rule is placed after a redirect rule.
481 * Return 1 if the warning has been emitted, otherwise 0.
482 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100483int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200484{
485 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
486 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
487 file, line, arg);
488 return 1;
489 }
490 return 0;
491}
492
493/* Report a warning if a rule is placed after a 'use_backend' rule.
494 * Return 1 if the warning has been emitted, otherwise 0.
495 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100496int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200497{
498 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
499 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
500 file, line, arg);
501 return 1;
502 }
503 return 0;
504}
505
Willy Tarreauee445d92014-04-23 01:39:04 +0200506/* Report a warning if a rule is placed after a 'use-server' rule.
507 * Return 1 if the warning has been emitted, otherwise 0.
508 */
509int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
510{
511 if (!LIST_ISEMPTY(&proxy->server_rules)) {
512 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
513 file, line, arg);
514 return 1;
515 }
516 return 0;
517}
518
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519/* report a warning if a redirect rule is dangerously placed */
520int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200521{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200523 warnif_rule_after_use_server(proxy, file, line, arg);
524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a reqadd rule is dangerously placed */
527int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_redirect(proxy, file, line, arg) ||
530 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200531}
532
Willy Tarreaud39ad442016-11-25 15:16:12 +0100533/* report a warning if a reqxxx rule is dangerously placed */
534int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200535{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100536 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
537 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200538}
539
540/* report a warning if an http-request rule is dangerously placed */
541int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
542{
Willy Tarreau61d18892009-03-31 10:49:21 +0200543 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100544 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200545}
546
Willy Tarreaud39ad442016-11-25 15:16:12 +0100547/* report a warning if a block rule is dangerously placed */
548int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200549{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100550 return warnif_rule_after_http_req(proxy, file, line, arg) ||
551 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200552}
553
Willy Tarreaud39ad442016-11-25 15:16:12 +0100554/* report a warning if a "tcp request content" rule is dangerously placed */
555int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200556{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100557 return warnif_rule_after_block(proxy, file, line, arg) ||
558 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200559}
560
Willy Tarreaud39ad442016-11-25 15:16:12 +0100561/* report a warning if a "tcp request session" rule is dangerously placed */
562int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200563{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100564 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
565 warnif_misplaced_tcp_cont(proxy, file, line, arg);
566}
567
568/* report a warning if a "tcp request connection" rule is dangerously placed */
569int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
570{
571 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
572 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200573}
574
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575/* Report it if a request ACL condition uses some keywords that are incompatible
576 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
577 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
578 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100579 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100580static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100581{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200583 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100584
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100585 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100586 return 0;
587
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100588 acl = acl_cond_conflicts(cond, where);
589 if (acl) {
590 if (acl->name && *acl->name)
591 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
592 file, line, acl->name, sample_ckp_names(where));
593 else
594 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 +0200595 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100596 return ERR_WARN;
597 }
598 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100599 return 0;
600
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100601 if (acl->name && *acl->name)
602 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200603 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100604 else
605 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200606 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100607 return ERR_WARN;
608}
609
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 * parse a line in a <global> section. Returns the error code, 0 if OK, or
612 * any combination of :
613 * - ERR_ABORT: must abort ASAP
614 * - ERR_FATAL: we can continue parsing but not start the service
615 * - ERR_WARN: a warning has been emitted
616 * - ERR_ALERT: an alert has been emitted
617 * Only the two first ones can stop processing, the two others are just
618 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200620int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621{
Willy Tarreau058e9072009-07-20 09:30:05 +0200622 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200623 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624
625 if (!strcmp(args[0], "global")) { /* new section */
626 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200627 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 }
630 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200631 if (alertif_too_many_args(0, file, linenum, args, &err_code))
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 global.mode |= MODE_DAEMON;
634 }
635 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200636 if (alertif_too_many_args(0, file, linenum, args, &err_code))
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 global.mode |= MODE_DEBUG;
639 }
640 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(0, file, linenum, args, &err_code))
642 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100643 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200645 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200646 if (alertif_too_many_args(0, file, linenum, args, &err_code))
647 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100648 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200651 if (alertif_too_many_args(0, file, linenum, args, &err_code))
652 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100653 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100655 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200656 if (alertif_too_many_args(0, file, linenum, args, &err_code))
657 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100658 global.tune.options &= ~GTUNE_USE_SPLICE;
659 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200660 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200663 global.tune.options &= ~GTUNE_USE_GAI;
664 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000665 else if (!strcmp(args[0], "noreuseport")) {
666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
668 global.tune.options &= ~GTUNE_USE_REUSEPORT;
669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(0, file, linenum, args, &err_code))
672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673 global.mode |= MODE_QUIET;
674 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200676 if (alertif_too_many_args(1, file, linenum, args, &err_code))
677 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200678 if (global.tune.maxpollevents != 0) {
679 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT;
681 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 }
683 if (*(args[1]) == 0) {
684 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200685 err_code |= ERR_ALERT | ERR_FATAL;
686 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200687 }
688 global.tune.maxpollevents = atol(args[1]);
689 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200691 if (alertif_too_many_args(1, file, linenum, args, &err_code))
692 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100693 if (global.tune.maxaccept != 0) {
694 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT;
696 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 }
698 if (*(args[1]) == 0) {
699 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100702 }
703 global.tune.maxaccept = atol(args[1]);
704 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200705 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
707 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200708 if (*(args[1]) == 0) {
709 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 global.tune.chksize = atol(args[1]);
714 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100715 else if (!strcmp(args[0], "tune.recv_enough")) {
716 if (alertif_too_many_args(1, file, linenum, args, &err_code))
717 goto out;
718 if (*(args[1]) == 0) {
719 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723 global.tune.recv_enough = atol(args[1]);
724 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100725 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200726 if (alertif_too_many_args(1, file, linenum, args, &err_code))
727 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 global.tune.buf_limit = atol(args[1]);
734 if (global.tune.buf_limit) {
735 if (global.tune.buf_limit < 3)
736 global.tune.buf_limit = 3;
737 if (global.tune.buf_limit <= global.tune.reserved_bufs)
738 global.tune.buf_limit = global.tune.reserved_bufs + 1;
739 }
740 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100741 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
743 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100744 if (*(args[1]) == 0) {
745 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749 global.tune.reserved_bufs = atol(args[1]);
750 if (global.tune.reserved_bufs < 2)
751 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100752 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
753 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100754 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200755 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200756 if (alertif_too_many_args(1, file, linenum, args, &err_code))
757 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200764 if (global.tune.bufsize <= 0) {
765 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100769 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100770 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200771 }
772 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200773 if (alertif_too_many_args(1, file, linenum, args, &err_code))
774 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200775 if (*(args[1]) == 0) {
776 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT | ERR_FATAL;
778 goto out;
779 }
780 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200781 if (global.tune.maxrewrite < 0) {
782 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200786 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100787 else if (!strcmp(args[0], "tune.idletimer")) {
788 unsigned int idle;
789 const char *res;
790
William Lallemand1a748ae2015-05-19 16:37:23 +0200791 if (alertif_too_many_args(1, file, linenum, args, &err_code))
792 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798
799 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
800 if (res) {
801 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
802 file, linenum, *res, args[0]);
803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
805 }
806
807 if (idle > 65535) {
808 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.idle_timer = idle;
813 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100814 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200815 if (alertif_too_many_args(1, file, linenum, args, &err_code))
816 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100817 if (global.tune.client_rcvbuf != 0) {
818 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
819 err_code |= ERR_ALERT;
820 goto out;
821 }
822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
826 }
827 global.tune.client_rcvbuf = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200830 if (alertif_too_many_args(1, file, linenum, args, &err_code))
831 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100832 if (global.tune.server_rcvbuf != 0) {
833 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
834 err_code |= ERR_ALERT;
835 goto out;
836 }
837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 global.tune.server_rcvbuf = atol(args[1]);
843 }
844 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200845 if (alertif_too_many_args(1, file, linenum, args, &err_code))
846 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100847 if (global.tune.client_sndbuf != 0) {
848 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
849 err_code |= ERR_ALERT;
850 goto out;
851 }
852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857 global.tune.client_sndbuf = atol(args[1]);
858 }
859 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200860 if (alertif_too_many_args(1, file, linenum, args, &err_code))
861 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100862 if (global.tune.server_sndbuf != 0) {
863 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT;
865 goto out;
866 }
867 if (*(args[1]) == 0) {
868 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872 global.tune.server_sndbuf = atol(args[1]);
873 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200874 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200875 if (alertif_too_many_args(1, file, linenum, args, &err_code))
876 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.tune.pipesize = atol(args[1]);
883 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100884 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200885 if (alertif_too_many_args(1, file, linenum, args, &err_code))
886 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892 global.tune.cookie_len = atol(args[1]) + 1;
893 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200894 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200895 if (alertif_too_many_args(1, file, linenum, args, &err_code))
896 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200897 if (*(args[1]) == 0) {
898 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 global.tune.max_http_hdr = atol(args[1]);
903 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100904 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
905#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200906 if (alertif_too_many_args(1, file, linenum, args, &err_code))
907 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100908 if (*args[1]) {
909 global.tune.zlibmemlevel = atoi(args[1]);
910 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
911 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
912 file, linenum, args[0]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
916 } else {
917 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
918 file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922#else
923 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
924 err_code |= ERR_ALERT | ERR_FATAL;
925 goto out;
926#endif
927 }
928 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
929#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200930 if (alertif_too_many_args(1, file, linenum, args, &err_code))
931 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100932 if (*args[1]) {
933 global.tune.zlibwindowsize = atoi(args[1]);
934 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
935 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
936 file, linenum, args[0]);
937 err_code |= ERR_ALERT | ERR_FATAL;
938 goto out;
939 }
940 } else {
941 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
942 file, linenum, args[0]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946#else
947 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950#endif
951 }
William Lallemandf3747832012-11-09 12:33:10 +0100952 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200953 if (alertif_too_many_args(1, file, linenum, args, &err_code))
954 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100955 if (*args[1]) {
956 global.tune.comp_maxlevel = atoi(args[1]);
957 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
958 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
959 file, linenum, args[0]);
960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
962 }
963 } else {
964 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
965 file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200970 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
971 if (*args[1]) {
972 global.tune.pattern_cache = atoi(args[1]);
973 if (global.tune.pattern_cache < 0) {
974 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
975 file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979 } else {
980 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
981 file, linenum, args[0]);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984 }
985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200987 if (alertif_too_many_args(1, file, linenum, args, &err_code))
988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200990 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100999 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1000 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]);
1001 err_code |= ERR_WARN;
1002 goto out;
1003 }
1004
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001007 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001009 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001010 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001011 err_code |= ERR_ALERT;
1012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013 }
1014 if (*(args[1]) == 0) {
1015 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001018 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001019 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1020 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]);
1021 err_code |= ERR_WARN;
1022 goto out;
1023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
Simon Horman98637e52014-06-20 12:30:16 +09001025 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001026 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1027 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001028 global.external_check = 1;
1029 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001030 /* user/group name handling */
1031 else if (!strcmp(args[0], "user")) {
1032 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001033 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1034 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001035 if (global.uid != 0) {
1036 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT;
1038 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001039 }
1040 errno = 0;
1041 ha_user = getpwnam(args[1]);
1042 if (ha_user != NULL) {
1043 global.uid = (int)ha_user->pw_uid;
1044 }
1045 else {
1046 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 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001048 }
1049 }
1050 else if (!strcmp(args[0], "group")) {
1051 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001052 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1053 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001054 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001055 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT;
1057 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001058 }
1059 errno = 0;
1060 ha_group = getgrnam(args[1]);
1061 if (ha_group != NULL) {
1062 global.gid = (int)ha_group->gr_gid;
1063 }
1064 else {
1065 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 +02001066 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001067 }
1068 }
1069 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001071 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
1078 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001079 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1080 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1081 file, linenum, args[0], LONGBITS, global.nbproc);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 }
1086 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001087 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 if (global.maxconn != 0) {
1090 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 err_code |= ERR_ALERT;
1092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 }
1094 if (*(args[1]) == 0) {
1095 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 }
1099 global.maxconn = atol(args[1]);
1100#ifdef SYSTEM_MAXCONN
1101 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1102 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);
1103 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001104 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 }
1106#endif /* SYSTEM_MAXCONN */
1107 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001108 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1109#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1111 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001112 if (*(args[1]) == 0) {
1113 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117 free(global.listen_default_ciphers);
1118 global.listen_default_ciphers = strdup(args[1]);
1119#else
1120 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
1123#endif
1124 }
1125 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1126#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001127 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1128 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001129 if (*(args[1]) == 0) {
1130 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
1133 }
1134 free(global.connect_default_ciphers);
1135 global.connect_default_ciphers = strdup(args[1]);
1136#else
1137 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto out;
1140#endif
1141 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001142#ifdef USE_OPENSSL
1143#ifndef OPENSSL_NO_DH
1144 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1145 if (*(args[1]) == 0) {
1146 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1147 err_code |= ERR_ALERT | ERR_FATAL;
1148 goto out;
1149 }
1150 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1151 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
1154 }
1155 }
1156#endif
1157#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001158 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001159 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1160 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001161 if (*(args[1]) == 0) {
1162 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT | ERR_FATAL;
1164 goto out;
1165 }
1166 if (strcmp(args[1],"none") == 0)
1167 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1168 else if (strcmp(args[1],"required") == 0)
1169 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1170 else {
1171 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001176 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001177 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1178 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001179 if (global.cps_lim != 0) {
1180 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1181 err_code |= ERR_ALERT;
1182 goto out;
1183 }
1184 if (*(args[1]) == 0) {
1185 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
1189 global.cps_lim = atol(args[1]);
1190 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001191 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001192 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1193 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001194 if (global.sps_lim != 0) {
1195 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1196 err_code |= ERR_ALERT;
1197 goto out;
1198 }
1199 if (*(args[1]) == 0) {
1200 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
1203 }
1204 global.sps_lim = atol(args[1]);
1205 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001206 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001207 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1208 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001209 if (global.ssl_lim != 0) {
1210 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1211 err_code |= ERR_ALERT;
1212 goto out;
1213 }
1214 if (*(args[1]) == 0) {
1215 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218 }
1219 global.ssl_lim = atol(args[1]);
1220 }
William Lallemandd85f9172012-11-09 17:05:39 +01001221 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001222 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1223 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 global.comp_rate_lim = atoi(args[1]) * 1024;
1230 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001231 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001232 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1233 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001234 if (global.maxpipes != 0) {
1235 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001236 err_code |= ERR_ALERT;
1237 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001238 }
1239 if (*(args[1]) == 0) {
1240 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001243 }
1244 global.maxpipes = atol(args[1]);
1245 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001246 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001247 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1248 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001249 if (*(args[1]) == 0) {
1250 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
William Lallemande3a7d992012-11-20 11:25:20 +01001254 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001255 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001256 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001257 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1258 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001259 if (*(args[1]) == 0) {
1260 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
1263 }
1264 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001265 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001266 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001270 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001271
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001273 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 if (global.rlimit_nofile != 0) {
1276 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001277 err_code |= ERR_ALERT;
1278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 }
1280 if (*(args[1]) == 0) {
1281 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
1285 global.rlimit_nofile = atol(args[1]);
1286 }
1287 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001288 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001290 if (global.chroot != NULL) {
1291 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001292 err_code |= ERR_ALERT;
1293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001294 }
1295 if (*(args[1]) == 0) {
1296 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 }
1300 global.chroot = strdup(args[1]);
1301 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001302 else if (!strcmp(args[0], "description")) {
1303 int i, len=0;
1304 char *d;
1305
1306 if (!*args[1]) {
1307 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1308 file, linenum, args[0]);
1309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
1311 }
1312
Willy Tarreau348acfe2014-04-14 15:00:39 +02001313 for (i = 1; *args[i]; i++)
1314 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001315
1316 if (global.desc)
1317 free(global.desc);
1318
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001319 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001320
Willy Tarreau348acfe2014-04-14 15:00:39 +02001321 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1322 for (i = 2; *args[i]; i++)
1323 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001324 }
1325 else if (!strcmp(args[0], "node")) {
1326 int i;
1327 char c;
1328
William Lallemand1a748ae2015-05-19 16:37:23 +02001329 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1330 goto out;
1331
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001332 for (i=0; args[1][i]; i++) {
1333 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001334 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1335 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001336 break;
1337 }
1338
1339 if (!i || args[1][i]) {
1340 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1341 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1342 file, linenum, args[0]);
1343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
1345 }
1346
1347 if (global.node)
1348 free(global.node);
1349
1350 global.node = strdup(args[1]);
1351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001353 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355 if (global.pidfile != NULL) {
1356 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001357 err_code |= ERR_ALERT;
1358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 }
1360 if (*(args[1]) == 0) {
1361 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 }
1365 global.pidfile = strdup(args[1]);
1366 }
Emeric Bruned760922010-10-22 17:59:25 +02001367 else if (!strcmp(args[0], "unix-bind")) {
1368 int cur_arg = 1;
1369 while (*(args[cur_arg])) {
1370 if (!strcmp(args[cur_arg], "prefix")) {
1371 if (global.unix_bind.prefix != NULL) {
1372 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1373 err_code |= ERR_ALERT;
1374 cur_arg += 2;
1375 continue;
1376 }
1377
1378 if (*(args[cur_arg+1]) == 0) {
1379 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
1382 }
1383 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1384 cur_arg += 2;
1385 continue;
1386 }
1387
1388 if (!strcmp(args[cur_arg], "mode")) {
1389
1390 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1391 cur_arg += 2;
1392 continue;
1393 }
1394
1395 if (!strcmp(args[cur_arg], "uid")) {
1396
1397 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1398 cur_arg += 2;
1399 continue;
1400 }
1401
1402 if (!strcmp(args[cur_arg], "gid")) {
1403
1404 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1405 cur_arg += 2;
1406 continue;
1407 }
1408
1409 if (!strcmp(args[cur_arg], "user")) {
1410 struct passwd *user;
1411
1412 user = getpwnam(args[cur_arg + 1]);
1413 if (!user) {
1414 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1415 file, linenum, args[0], args[cur_arg + 1 ]);
1416 err_code |= ERR_ALERT | ERR_FATAL;
1417 goto out;
1418 }
1419
1420 global.unix_bind.ux.uid = user->pw_uid;
1421 cur_arg += 2;
1422 continue;
1423 }
1424
1425 if (!strcmp(args[cur_arg], "group")) {
1426 struct group *group;
1427
1428 group = getgrnam(args[cur_arg + 1]);
1429 if (!group) {
1430 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1431 file, linenum, args[0], args[cur_arg + 1 ]);
1432 err_code |= ERR_ALERT | ERR_FATAL;
1433 goto out;
1434 }
1435
1436 global.unix_bind.ux.gid = group->gr_gid;
1437 cur_arg += 2;
1438 continue;
1439 }
1440
Willy Tarreaub48f9582011-09-05 01:17:06 +02001441 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001442 file, linenum, args[0]);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446 }
William Lallemand0f99e342011-10-12 17:50:54 +02001447 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1448 /* delete previous herited or defined syslog servers */
1449 struct logsrv *back;
1450 struct logsrv *tmp;
1451
1452 if (*(args[1]) != 0) {
1453 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
1456 }
1457
1458 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1459 LIST_DEL(&tmp->list);
1460 free(tmp);
1461 }
1462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001464 struct sockaddr_storage *sk;
1465 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001466 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001467 int arg = 0;
1468 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001469
William Lallemand1a748ae2015-05-19 16:37:23 +02001470 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1471 goto out;
1472
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 if (*(args[1]) == 0 || *(args[2]) == 0) {
1474 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477 }
William Lallemand0f99e342011-10-12 17:50:54 +02001478
Vincent Bernat02779b62016-04-03 13:48:43 +02001479 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001480
Willy Tarreau18324f52014-06-27 18:10:07 +02001481 /* just after the address, a length may be specified */
1482 if (strcmp(args[arg+2], "len") == 0) {
1483 len = atoi(args[arg+3]);
1484 if (len < 80 || len > 65535) {
1485 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1486 file, linenum, args[arg+3]);
1487 err_code |= ERR_ALERT | ERR_FATAL;
1488 goto out;
1489 }
1490 logsrv->maxlen = len;
1491
1492 /* skip these two args */
1493 arg += 2;
1494 }
1495 else
1496 logsrv->maxlen = MAX_SYSLOG_LEN;
1497
1498 if (logsrv->maxlen > global.max_syslog_len) {
1499 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001500 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1501 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1502 logline = my_realloc2(logline, global.max_syslog_len + 1);
1503 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001504 }
1505
Dragan Dosen1322d092015-09-22 16:05:32 +02001506 /* after the length, a format may be specified */
1507 if (strcmp(args[arg+2], "format") == 0) {
1508 logsrv->format = get_log_format(args[arg+3]);
1509 if (logsrv->format < 0) {
1510 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001512 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001513 goto out;
1514 }
1515
1516 /* skip these two args */
1517 arg += 2;
1518 }
1519
David Carlier97880bb2016-04-08 10:35:26 +01001520 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1521 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001522 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001523 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001524
Willy Tarreau18324f52014-06-27 18:10:07 +02001525 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001526 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001527 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001528 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001529 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 }
1531
William Lallemand0f99e342011-10-12 17:50:54 +02001532 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001533 if (*(args[arg+3])) {
1534 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001535 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001536 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001538 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539 }
1540 }
1541
William Lallemand0f99e342011-10-12 17:50:54 +02001542 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001543 if (*(args[arg+4])) {
1544 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001545 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001546 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001547 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001548 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001549 }
1550 }
1551
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001552 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001553 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001554 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001555 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001556 free(logsrv);
1557 goto out;
1558 }
1559 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001560
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001561 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001562 if (port1 != port2) {
1563 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1564 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001565 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001566 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001567 goto out;
1568 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001569
William Lallemand0f99e342011-10-12 17:50:54 +02001570 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001571 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001572 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574
William Lallemand0f99e342011-10-12 17:50:54 +02001575 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001576 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001577 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1578 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001579
1580 if (global.log_send_hostname != NULL) {
1581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1582 err_code |= ERR_ALERT;
1583 goto out;
1584 }
1585
1586 if (*(args[1]))
1587 name = args[1];
1588 else
1589 name = hostname;
1590
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001591 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001592 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001593 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001594 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1595 if (global.server_state_base != NULL) {
1596 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1597 err_code |= ERR_ALERT;
1598 goto out;
1599 }
1600
1601 if (!*(args[1])) {
1602 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1603 err_code |= ERR_FATAL;
1604 goto out;
1605 }
1606
1607 global.server_state_base = strdup(args[1]);
1608 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001609 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1610 if (global.server_state_file != NULL) {
1611 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1612 err_code |= ERR_ALERT;
1613 goto out;
1614 }
1615
1616 if (!*(args[1])) {
1617 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1618 err_code |= ERR_FATAL;
1619 goto out;
1620 }
1621
1622 global.server_state_file = strdup(args[1]);
1623 }
Kevinm48936af2010-12-22 16:08:21 +00001624 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001625 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1626 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001627 if (*(args[1]) == 0) {
1628 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
1631 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001632 chunk_destroy(&global.log_tag);
1633 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001634 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001635 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001636 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1637 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001638 if (global.spread_checks != 0) {
1639 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001640 err_code |= ERR_ALERT;
1641 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001642 }
1643 if (*(args[1]) == 0) {
1644 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001647 }
1648 global.spread_checks = atol(args[1]);
1649 if (global.spread_checks < 0 || global.spread_checks > 50) {
1650 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001654 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1655 const char *err;
1656 unsigned int val;
1657
William Lallemand1a748ae2015-05-19 16:37:23 +02001658 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1659 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001660 if (*(args[1]) == 0) {
1661 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
1664 }
1665
1666 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1667 if (err) {
1668 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1669 err_code |= ERR_ALERT | ERR_FATAL;
1670 }
1671 global.max_spread_checks = val;
1672 if (global.max_spread_checks < 0) {
1673 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1674 err_code |= ERR_ALERT | ERR_FATAL;
1675 }
1676 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001677 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1678#ifdef USE_CPU_AFFINITY
1679 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001680 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001681 unsigned long cpus = 0;
1682
1683 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001684 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001685 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001686 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001687 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001688 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001689 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001690 proc = atol(args[1]);
1691 if (proc >= 1 && proc <= LONGBITS)
1692 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001693 }
1694
1695 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001696 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",
1697 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001698 err_code |= ERR_ALERT | ERR_FATAL;
1699 goto out;
1700 }
1701
1702 cur_arg = 2;
1703 while (*args[cur_arg]) {
1704 unsigned int low, high;
1705
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001706 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001707 char *dash = strchr(args[cur_arg], '-');
1708
1709 low = high = str2uic(args[cur_arg]);
1710 if (dash)
1711 high = str2uic(dash + 1);
1712
1713 if (high < low) {
1714 unsigned int swap = low;
1715 low = high;
1716 high = swap;
1717 }
1718
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001719 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001720 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001721 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
1724 }
1725
1726 while (low <= high)
1727 cpus |= 1UL << low++;
1728 }
1729 else {
1730 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1731 file, linenum, args[0], args[cur_arg]);
1732 err_code |= ERR_ALERT | ERR_FATAL;
1733 goto out;
1734 }
1735 cur_arg++;
1736 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001737 for (i = 0; i < LONGBITS; i++)
1738 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001739 global.cpu_map[i] = cpus;
1740#else
1741 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
1744#endif
1745 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001746 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1747 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1748 goto out;
1749
1750 if (*(args[2]) == 0) {
1751 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755
1756 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1757 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1758 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1759 err_code |= ERR_ALERT | ERR_FATAL;
1760 goto out;
1761 }
1762 }
1763 else if (!strcmp(args[0], "unsetenv")) {
1764 int arg;
1765
1766 if (*(args[1]) == 0) {
1767 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1768 err_code |= ERR_ALERT | ERR_FATAL;
1769 goto out;
1770 }
1771
1772 for (arg = 1; *args[arg]; arg++) {
1773 if (unsetenv(args[arg]) != 0) {
1774 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
1777 }
1778 }
1779 }
1780 else if (!strcmp(args[0], "resetenv")) {
1781 extern char **environ;
1782 char **env = environ;
1783
1784 /* args contain variable names to keep, one per argument */
1785 while (*env) {
1786 int arg;
1787
1788 /* look for current variable in among all those we want to keep */
1789 for (arg = 1; *args[arg]; arg++) {
1790 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1791 (*env)[strlen(args[arg])] == '=')
1792 break;
1793 }
1794
1795 /* delete this variable */
1796 if (!*args[arg]) {
1797 char *delim = strchr(*env, '=');
1798
1799 if (!delim || delim - *env >= trash.size) {
1800 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804
1805 memcpy(trash.str, *env, delim - *env);
1806 trash.str[delim - *env] = 0;
1807
1808 if (unsetenv(trash.str) != 0) {
1809 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813 }
1814 else
1815 env++;
1816 }
1817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001819 struct cfg_kw_list *kwl;
1820 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001821 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001822
1823 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1824 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1825 if (kwl->kw[index].section != CFG_GLOBAL)
1826 continue;
1827 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001828 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001829 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001830 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001831 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001832 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001833 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001834 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001835 err_code |= ERR_WARN;
1836 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001837 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001838 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001839 }
1840 }
1841 }
1842
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001846
Willy Tarreau058e9072009-07-20 09:30:05 +02001847 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001848 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001849 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850}
1851
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001852void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001854 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 defproxy.mode = PR_MODE_TCP;
1856 defproxy.state = PR_STNEW;
1857 defproxy.maxconn = cfg_maxpconn;
1858 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001859 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001860 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001861
Simon Horman66183002013-02-23 10:16:43 +09001862 defproxy.defsrv.check.inter = DEF_CHKINTR;
1863 defproxy.defsrv.check.fastinter = 0;
1864 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001865 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1866 defproxy.defsrv.agent.fastinter = 0;
1867 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001868 defproxy.defsrv.check.rise = DEF_RISETIME;
1869 defproxy.defsrv.check.fall = DEF_FALLTIME;
1870 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1871 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001872 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001873 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001874 defproxy.defsrv.maxqueue = 0;
1875 defproxy.defsrv.minconn = 0;
1876 defproxy.defsrv.maxconn = 0;
1877 defproxy.defsrv.slowstart = 0;
1878 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1879 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1880 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001881
1882 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001883 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884}
1885
Willy Tarreauade5ec42010-01-28 19:33:49 +01001886
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1888 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1889 * ERR_FATAL in case of error.
1890 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001891static int create_cond_regex_rule(const char *file, int line,
1892 struct proxy *px, int dir, int action, int flags,
1893 const char *cmd, const char *reg, const char *repl,
1894 const char **cond_start)
1895{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001896 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001897 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001898 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001899 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001900 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001901 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001902 int cs;
1903 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001904
1905 if (px == &defproxy) {
1906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001907 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001908 goto err;
1909 }
1910
1911 if (*reg == 0) {
1912 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001913 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001914 goto err;
1915 }
1916
Christopher Faulet898566e2016-10-26 11:06:28 +02001917 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001918 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001919
Willy Tarreau5321c422010-01-28 20:35:13 +01001920 if (cond_start &&
1921 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001922 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1923 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1924 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001925 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001926 goto err;
1927 }
1928 }
1929 else if (cond_start && **cond_start) {
1930 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1931 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001932 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001933 goto err;
1934 }
1935
Willy Tarreau63af98d2014-05-18 08:11:41 +02001936 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001937 (dir == SMP_OPT_DIR_REQ) ?
1938 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1939 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1940 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001941
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001942 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001943 if (!preg) {
1944 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001945 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001946 goto err;
1947 }
1948
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001949 cs = !(flags & REG_ICASE);
1950 cap = !(flags & REG_NOSUB);
1951 error = NULL;
1952 if (!regex_comp(reg, preg, cs, cap, &error)) {
1953 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1954 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001955 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001956 goto err;
1957 }
1958
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001959 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001960 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001961 if (repl && err) {
1962 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1963 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001964 ret_code |= ERR_ALERT | ERR_FATAL;
1965 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001966 }
1967
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001968 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001969 ret_code |= ERR_WARN;
1970
1971 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001972
Willy Tarreau63af98d2014-05-18 08:11:41 +02001973 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001974 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001975 err:
1976 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001977 free(errmsg);
1978 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001979}
1980
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981/*
William Lallemand51097192015-04-14 16:35:22 +02001982 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001983 * Returns the error code, 0 if OK, or any combination of :
1984 * - ERR_ABORT: must abort ASAP
1985 * - ERR_FATAL: we can continue parsing but not start the service
1986 * - ERR_WARN: a warning has been emitted
1987 * - ERR_ALERT: an alert has been emitted
1988 * Only the two first ones can stop processing, the two others are just
1989 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001991int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1992{
1993 static struct peers *curpeers = NULL;
1994 struct peer *newpeer = NULL;
1995 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001996 struct bind_conf *bind_conf;
1997 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001998 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001999 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002000
2001 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002002 if (!*args[1]) {
2003 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002004 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002005 goto out;
2006 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002007
William Lallemand6e62fb62015-04-28 16:55:23 +02002008 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2009 goto out;
2010
Emeric Brun32da3c42010-09-23 18:39:19 +02002011 err = invalid_char(args[1]);
2012 if (err) {
2013 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2014 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002015 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002016 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002017 }
2018
2019 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2020 /*
2021 * If there are two proxies with the same name only following
2022 * combinations are allowed:
2023 */
2024 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002025 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 +02002026 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002028 }
2029 }
2030
Vincent Bernat02779b62016-04-03 13:48:43 +02002031 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002032 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2033 err_code |= ERR_ALERT | ERR_ABORT;
2034 goto out;
2035 }
2036
2037 curpeers->next = peers;
2038 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002039 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002040 curpeers->conf.line = linenum;
2041 curpeers->last_change = now.tv_sec;
2042 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002043 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002044 }
2045 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002046 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002047 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002048 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002049
2050 if (!*args[2]) {
2051 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2052 file, linenum, args[0]);
2053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
2055 }
2056
2057 err = invalid_char(args[1]);
2058 if (err) {
2059 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2060 file, linenum, *err, args[1]);
2061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
2063 }
2064
Vincent Bernat02779b62016-04-03 13:48:43 +02002065 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002066 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2067 err_code |= ERR_ALERT | ERR_ABORT;
2068 goto out;
2069 }
2070
2071 /* the peers are linked backwards first */
2072 curpeers->count++;
2073 newpeer->next = curpeers->remote;
2074 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002075 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002076 newpeer->conf.line = linenum;
2077
2078 newpeer->last_change = now.tv_sec;
2079 newpeer->id = strdup(args[1]);
2080
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002081 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002082 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002083 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002084 err_code |= ERR_ALERT | ERR_FATAL;
2085 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002086 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002087
2088 proto = protocol_by_family(sk->ss_family);
2089 if (!proto || !proto->connect) {
2090 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2091 file, linenum, args[0], args[1]);
2092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
2094 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002095
2096 if (port1 != port2) {
2097 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2098 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
2101 }
2102
Willy Tarreau2aa38802013-02-20 19:20:59 +01002103 if (!port1) {
2104 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2105 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
2108 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002109
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002111 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002112 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002113 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002114
Emeric Brun32da3c42010-09-23 18:39:19 +02002115 if (strcmp(newpeer->id, localpeer) == 0) {
2116 /* Current is local peer, it define a frontend */
2117 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002118 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002119
2120 if (!curpeers->peers_fe) {
2121 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2122 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2123 err_code |= ERR_ALERT | ERR_ABORT;
2124 goto out;
2125 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002126
Willy Tarreau237250c2011-07-29 01:49:03 +02002127 init_new_proxy(curpeers->peers_fe);
2128 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002129 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002130 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2131 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002132 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002133
2134 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2135
Willy Tarreau902636f2013-03-10 19:44:48 +01002136 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2137 if (errmsg && *errmsg) {
2138 indent_msg(&errmsg, 2);
2139 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002140 }
2141 else
2142 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2143 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002144 err_code |= ERR_FATAL;
2145 goto out;
2146 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002147
2148 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002149 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002150 l->maxconn = curpeers->peers_fe->maxconn;
2151 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002152 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002153 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002154 l->analysers |= curpeers->peers_fe->fe_req_ana;
2155 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002156 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2157 global.maxsock += l->maxconn;
2158 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002159 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002160 else {
2161 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2162 file, linenum, args[0], args[1],
2163 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2164 err_code |= ERR_FATAL;
2165 goto out;
2166 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002167 }
2168 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002169 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2170 curpeers->state = PR_STSTOPPED;
2171 }
2172 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2173 curpeers->state = PR_STNEW;
2174 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002175 else if (*args[0] != 0) {
2176 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
2181out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002182 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002183 return err_code;
2184}
2185
Baptiste Assmann325137d2015-04-13 23:40:55 +02002186/*
2187 * Parse a <resolvers> section.
2188 * Returns the error code, 0 if OK, or any combination of :
2189 * - ERR_ABORT: must abort ASAP
2190 * - ERR_FATAL: we can continue parsing but not start the service
2191 * - ERR_WARN: a warning has been emitted
2192 * - ERR_ALERT: an alert has been emitted
2193 * Only the two first ones can stop processing, the two others are just
2194 * indicators.
2195 */
2196int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2197{
2198 static struct dns_resolvers *curr_resolvers = NULL;
2199 struct dns_nameserver *newnameserver = NULL;
2200 const char *err;
2201 int err_code = 0;
2202 char *errmsg = NULL;
2203
2204 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2205 if (!*args[1]) {
2206 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2207 err_code |= ERR_ALERT | ERR_ABORT;
2208 goto out;
2209 }
2210
2211 err = invalid_char(args[1]);
2212 if (err) {
2213 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2214 file, linenum, *err, args[0], args[1]);
2215 err_code |= ERR_ALERT | ERR_ABORT;
2216 goto out;
2217 }
2218
2219 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2220 /* Error if two resolvers owns the same name */
2221 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2222 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2223 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2224 err_code |= ERR_ALERT | ERR_ABORT;
2225 }
2226 }
2227
Vincent Bernat02779b62016-04-03 13:48:43 +02002228 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002229 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2230 err_code |= ERR_ALERT | ERR_ABORT;
2231 goto out;
2232 }
2233
2234 /* default values */
2235 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2236 curr_resolvers->conf.file = strdup(file);
2237 curr_resolvers->conf.line = linenum;
2238 curr_resolvers->id = strdup(args[1]);
2239 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002240 /* default hold period for nx, other, refuse and timeout is 30s */
2241 curr_resolvers->hold.nx = 30000;
2242 curr_resolvers->hold.other = 30000;
2243 curr_resolvers->hold.refused = 30000;
2244 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002245 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002246 curr_resolvers->hold.valid = 10000;
2247 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002248 curr_resolvers->resolve_retries = 3;
2249 LIST_INIT(&curr_resolvers->nameserver_list);
2250 LIST_INIT(&curr_resolvers->curr_resolution);
2251 }
2252 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2253 struct sockaddr_storage *sk;
2254 int port1, port2;
2255 struct protocol *proto;
2256
2257 if (!*args[2]) {
2258 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2259 file, linenum, args[0]);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263
2264 err = invalid_char(args[1]);
2265 if (err) {
2266 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2267 file, linenum, *err, args[1]);
2268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
2270 }
2271
Baptiste Assmanna315c552015-11-02 22:55:49 +01002272 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2273 /* Error if two resolvers owns the same name */
2274 if (strcmp(newnameserver->id, args[1]) == 0) {
2275 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2276 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 }
2279 }
2280
Vincent Bernat02779b62016-04-03 13:48:43 +02002281 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002282 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2283 err_code |= ERR_ALERT | ERR_ABORT;
2284 goto out;
2285 }
2286
2287 /* the nameservers are linked backward first */
2288 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2289 curr_resolvers->count_nameservers++;
2290 newnameserver->resolvers = curr_resolvers;
2291 newnameserver->conf.file = strdup(file);
2292 newnameserver->conf.line = linenum;
2293 newnameserver->id = strdup(args[1]);
2294
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002295 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002296 if (!sk) {
2297 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301
2302 proto = protocol_by_family(sk->ss_family);
2303 if (!proto || !proto->connect) {
2304 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2305 file, linenum, args[0], args[1]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 if (port1 != port2) {
2311 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2312 file, linenum, args[0], args[1], args[2]);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002317 if (!port1 && !port2) {
2318 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2319 file, linenum, args[0], args[1]);
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323
Baptiste Assmann325137d2015-04-13 23:40:55 +02002324 newnameserver->addr = *sk;
2325 }
2326 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2327 const char *res;
2328 unsigned int time;
2329
2330 if (!*args[2]) {
2331 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2332 file, linenum, args[0]);
2333 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2334 err_code |= ERR_ALERT | ERR_FATAL;
2335 goto out;
2336 }
2337 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2338 if (res) {
2339 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2340 file, linenum, *res, args[0]);
2341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
2343 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002344 if (strcmp(args[1], "nx") == 0)
2345 curr_resolvers->hold.nx = time;
2346 else if (strcmp(args[1], "other") == 0)
2347 curr_resolvers->hold.other = time;
2348 else if (strcmp(args[1], "refused") == 0)
2349 curr_resolvers->hold.refused = time;
2350 else if (strcmp(args[1], "timeout") == 0)
2351 curr_resolvers->hold.timeout = time;
2352 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002353 curr_resolvers->hold.valid = time;
2354 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002355 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2356 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
2359 }
2360
2361 }
2362 else if (strcmp(args[0], "resolve_retries") == 0) {
2363 if (!*args[1]) {
2364 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2365 file, linenum, args[0]);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369 curr_resolvers->resolve_retries = atoi(args[1]);
2370 }
2371 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002372 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002373 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2374 file, linenum, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002378 else if (strcmp(args[1], "retry") == 0) {
2379 const char *res;
2380 unsigned int timeout_retry;
2381
2382 if (!*args[2]) {
2383 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2384 file, linenum, args[0], args[1]);
2385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
2387 }
2388 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2389 if (res) {
2390 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2391 file, linenum, *res, args[0], args[1]);
2392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
2394 }
2395 curr_resolvers->timeout.retry = timeout_retry;
2396 }
2397 else {
2398 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2399 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
2402 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002403 } /* neither "nameserver" nor "resolvers" */
2404 else if (*args[0] != 0) {
2405 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
2408 }
2409
2410 out:
2411 free(errmsg);
2412 return err_code;
2413}
Simon Horman0d16a402015-01-30 11:22:58 +09002414
2415/*
William Lallemand51097192015-04-14 16:35:22 +02002416 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002417 * Returns the error code, 0 if OK, or any combination of :
2418 * - ERR_ABORT: must abort ASAP
2419 * - ERR_FATAL: we can continue parsing but not start the service
2420 * - ERR_WARN: a warning has been emitted
2421 * - ERR_ALERT: an alert has been emitted
2422 * Only the two first ones can stop processing, the two others are just
2423 * indicators.
2424 */
2425int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2426{
2427 static struct mailers *curmailers = NULL;
2428 struct mailer *newmailer = NULL;
2429 const char *err;
2430 int err_code = 0;
2431 char *errmsg = NULL;
2432
2433 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2434 if (!*args[1]) {
2435 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2436 err_code |= ERR_ALERT | ERR_ABORT;
2437 goto out;
2438 }
2439
2440 err = invalid_char(args[1]);
2441 if (err) {
2442 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2443 file, linenum, *err, args[0], args[1]);
2444 err_code |= ERR_ALERT | ERR_ABORT;
2445 goto out;
2446 }
2447
2448 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2449 /*
2450 * If there are two proxies with the same name only following
2451 * combinations are allowed:
2452 */
2453 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002454 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 +09002455 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002457 }
2458 }
2459
Vincent Bernat02779b62016-04-03 13:48:43 +02002460 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002461 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2462 err_code |= ERR_ALERT | ERR_ABORT;
2463 goto out;
2464 }
2465
2466 curmailers->next = mailers;
2467 mailers = curmailers;
2468 curmailers->conf.file = strdup(file);
2469 curmailers->conf.line = linenum;
2470 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002471 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2472 * But need enough time so that timeouts don't occur
2473 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002474 }
2475 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2476 struct sockaddr_storage *sk;
2477 int port1, port2;
2478 struct protocol *proto;
2479
2480 if (!*args[2]) {
2481 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2482 file, linenum, args[0]);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487 err = invalid_char(args[1]);
2488 if (err) {
2489 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2490 file, linenum, *err, args[1]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494
Vincent Bernat02779b62016-04-03 13:48:43 +02002495 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002496 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2497 err_code |= ERR_ALERT | ERR_ABORT;
2498 goto out;
2499 }
2500
2501 /* the mailers are linked backwards first */
2502 curmailers->count++;
2503 newmailer->next = curmailers->mailer_list;
2504 curmailers->mailer_list = newmailer;
2505 newmailer->mailers = curmailers;
2506 newmailer->conf.file = strdup(file);
2507 newmailer->conf.line = linenum;
2508
2509 newmailer->id = strdup(args[1]);
2510
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002511 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002512 if (!sk) {
2513 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
2516 }
2517
2518 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002519 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2520 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002521 file, linenum, args[0], args[1]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525
2526 if (port1 != port2) {
2527 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2528 file, linenum, args[0], args[1], args[2]);
2529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
2531 }
2532
2533 if (!port1) {
2534 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2535 file, linenum, args[0], args[1], args[2]);
2536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
2538 }
2539
2540 newmailer->addr = *sk;
2541 newmailer->proto = proto;
2542 newmailer->xprt = &raw_sock;
2543 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002544 }
2545 else if (strcmp(args[0], "timeout") == 0) {
2546 if (!*args[1]) {
2547 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2548 file, linenum, args[0]);
2549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
2551 }
2552 else if (strcmp(args[1], "mail") == 0) {
2553 const char *res;
2554 unsigned int timeout_mail;
2555 if (!*args[2]) {
2556 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2557 file, linenum, args[0], args[1]);
2558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
2560 }
2561 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2562 if (res) {
2563 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2564 file, linenum, *res, args[0]);
2565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
2567 }
2568 if (timeout_mail <= 0) {
2569 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
2572 }
2573 curmailers->timeout.mail = timeout_mail;
2574 } else {
2575 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2576 file, linenum, args[0], args[1]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
2580 }
Simon Horman0d16a402015-01-30 11:22:58 +09002581 else if (*args[0] != 0) {
2582 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
2585 }
2586
2587out:
2588 free(errmsg);
2589 return err_code;
2590}
2591
Simon Horman9dc49962015-01-30 11:22:59 +09002592static void free_email_alert(struct proxy *p)
2593{
2594 free(p->email_alert.mailers.name);
2595 p->email_alert.mailers.name = NULL;
2596 free(p->email_alert.from);
2597 p->email_alert.from = NULL;
2598 free(p->email_alert.to);
2599 p->email_alert.to = NULL;
2600 free(p->email_alert.myhostname);
2601 p->email_alert.myhostname = NULL;
2602}
2603
Willy Tarreau3842f002009-06-14 11:39:52 +02002604int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605{
2606 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002607 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002608 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002609 int rc;
2610 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002611 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002612 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002613 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002614 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002615 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616
Willy Tarreau977b8e42006-12-29 14:19:17 +01002617 if (!strcmp(args[0], "listen"))
2618 rc = PR_CAP_LISTEN;
2619 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002620 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002621 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002622 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002623 else
2624 rc = PR_CAP_NONE;
2625
2626 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 if (!*args[1]) {
2628 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002629 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_ABORT;
2632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002634
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002635 err = invalid_char(args[1]);
2636 if (err) {
2637 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2638 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002640 }
2641
Willy Tarreau8f50b682015-05-26 11:45:02 +02002642 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2643 if (curproxy) {
2644 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2645 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2646 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002647 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002648 }
2649
Vincent Bernat02779b62016-04-03 13:48:43 +02002650 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002652 err_code |= ERR_ALERT | ERR_ABORT;
2653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002655
Willy Tarreau97cb7802010-01-03 20:23:58 +01002656 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 curproxy->next = proxy;
2658 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002659 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2660 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002661 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002663 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002664 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665
William Lallemand6e62fb62015-04-28 16:55:23 +02002666 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2667 if (curproxy->cap & PR_CAP_FE)
2668 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 }
2671
2672 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002673 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002674 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002675
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002678 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002679 curproxy->no_options = defproxy.no_options;
2680 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002681 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002682 curproxy->except_net = defproxy.except_net;
2683 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002684 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002685 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002687 if (defproxy.fwdfor_hdr_len) {
2688 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2689 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2690 }
2691
Willy Tarreaub86db342009-11-30 11:50:16 +01002692 if (defproxy.orgto_hdr_len) {
2693 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2694 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2695 }
2696
Mark Lamourinec2247f02012-01-04 13:02:01 -05002697 if (defproxy.server_id_hdr_len) {
2698 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2699 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2700 }
2701
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702 if (curproxy->cap & PR_CAP_FE) {
2703 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002704 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002705 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002706
2707 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002708 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2709 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002710
2711 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002715 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002716 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 curproxy->fullconn = defproxy.fullconn;
2718 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002719 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002720 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002722 if (defproxy.check_req) {
2723 curproxy->check_req = calloc(1, defproxy.check_len);
2724 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2725 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002726 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002728 if (defproxy.expect_str) {
2729 curproxy->expect_str = strdup(defproxy.expect_str);
2730 if (defproxy.expect_regex) {
2731 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002732 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2733 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002734 }
2735 }
2736
Willy Tarreau67402132012-05-31 20:40:20 +02002737 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738 if (defproxy.cookie_name)
2739 curproxy->cookie_name = strdup(defproxy.cookie_name);
2740 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002741 if (defproxy.cookie_domain)
2742 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002743
Willy Tarreau31936852010-10-06 16:59:56 +02002744 if (defproxy.cookie_maxidle)
2745 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2746
2747 if (defproxy.cookie_maxlife)
2748 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2749
Emeric Brun647caf12009-06-30 17:57:00 +02002750 if (defproxy.rdp_cookie_name)
2751 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2752 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2753
Willy Tarreau01732802007-11-01 22:48:15 +01002754 if (defproxy.url_param_name)
2755 curproxy->url_param_name = strdup(defproxy.url_param_name);
2756 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002757
Benoitaffb4812009-03-25 13:02:10 +01002758 if (defproxy.hh_name)
2759 curproxy->hh_name = strdup(defproxy.hh_name);
2760 curproxy->hh_len = defproxy.hh_len;
2761 curproxy->hh_match_domain = defproxy.hh_match_domain;
2762
Willy Tarreauef9a3602012-12-08 22:29:20 +01002763 if (defproxy.conn_src.iface_name)
2764 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2765 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002766 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002767#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002768 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002769#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002770 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002773 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002774 if (defproxy.capture_name)
2775 curproxy->capture_name = strdup(defproxy.capture_name);
2776 curproxy->capture_namelen = defproxy.capture_namelen;
2777 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779
Willy Tarreau977b8e42006-12-29 14:19:17 +01002780 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002781 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002782 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002783 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002784 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002785 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786 curproxy->mon_net = defproxy.mon_net;
2787 curproxy->mon_mask = defproxy.mon_mask;
2788 if (defproxy.monitor_uri)
2789 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2790 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002791 if (defproxy.defbe.name)
2792 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002793
2794 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002795 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2796 if (curproxy->conf.logformat_string &&
2797 curproxy->conf.logformat_string != default_http_log_format &&
2798 curproxy->conf.logformat_string != default_tcp_log_format &&
2799 curproxy->conf.logformat_string != clf_http_log_format)
2800 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2801
2802 if (defproxy.conf.lfs_file) {
2803 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2804 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2805 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002806
2807 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2808 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2809 if (curproxy->conf.logformat_sd_string &&
2810 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2811 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2812
2813 if (defproxy.conf.lfsd_file) {
2814 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2815 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2816 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002817 }
2818
2819 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002820 curproxy->timeout.connect = defproxy.timeout.connect;
2821 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002822 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002823 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002824 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002825 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002826 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002827 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002828 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002829 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002830 }
2831
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002833 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002834
2835 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002836 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002837 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002838 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002839 LIST_INIT(&node->list);
2840 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2841 }
2842
Willy Tarreau62a61232013-04-12 18:13:46 +02002843 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2844 if (curproxy->conf.uniqueid_format_string)
2845 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2846
Dragan Dosen43885c72015-10-01 13:18:13 +02002847 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002848
Willy Tarreau62a61232013-04-12 18:13:46 +02002849 if (defproxy.conf.uif_file) {
2850 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2851 curproxy->conf.uif_line = defproxy.conf.uif_line;
2852 }
William Lallemanda73203e2012-03-12 12:48:57 +01002853
2854 /* copy default header unique id */
2855 if (defproxy.header_unique_id)
2856 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2857
William Lallemand82fe75c2012-10-23 10:25:10 +02002858 /* default compression options */
2859 if (defproxy.comp != NULL) {
2860 curproxy->comp = calloc(1, sizeof(struct comp));
2861 curproxy->comp->algos = defproxy.comp->algos;
2862 curproxy->comp->types = defproxy.comp->types;
2863 }
2864
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002866 curproxy->conf.used_listener_id = EB_ROOT;
2867 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002868
Simon Horman98637e52014-06-20 12:30:16 +09002869 if (defproxy.check_path)
2870 curproxy->check_path = strdup(defproxy.check_path);
2871 if (defproxy.check_command)
2872 curproxy->check_command = strdup(defproxy.check_command);
2873
Simon Horman9dc49962015-01-30 11:22:59 +09002874 if (defproxy.email_alert.mailers.name)
2875 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2876 if (defproxy.email_alert.from)
2877 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2878 if (defproxy.email_alert.to)
2879 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2880 if (defproxy.email_alert.myhostname)
2881 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002882 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002883 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002884
Willy Tarreau93893792009-07-23 13:19:11 +02002885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
2887 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2888 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002889 /* FIXME-20070101: we should do this too at the end of the
2890 * config parsing to free all default values.
2891 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002892 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2893 err_code |= ERR_ABORT;
2894 goto out;
2895 }
2896
Willy Tarreaua534fea2008-08-03 12:19:50 +02002897 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002898 free(defproxy.check_command);
2899 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002900 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002901 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002902 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002903 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002904 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002905 free(defproxy.capture_name);
2906 free(defproxy.monitor_uri);
2907 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002908 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002909 free(defproxy.fwdfor_hdr_name);
2910 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002911 free(defproxy.orgto_hdr_name);
2912 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002913 free(defproxy.server_id_hdr_name);
2914 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002915 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002916 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002917 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002918 free(defproxy.expect_regex);
2919 defproxy.expect_regex = NULL;
2920 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002921
Willy Tarreau62a61232013-04-12 18:13:46 +02002922 if (defproxy.conf.logformat_string != default_http_log_format &&
2923 defproxy.conf.logformat_string != default_tcp_log_format &&
2924 defproxy.conf.logformat_string != clf_http_log_format)
2925 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002926
Willy Tarreau62a61232013-04-12 18:13:46 +02002927 free(defproxy.conf.uniqueid_format_string);
2928 free(defproxy.conf.lfs_file);
2929 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002930 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002931 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002932
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002933 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2934 free(defproxy.conf.logformat_sd_string);
2935 free(defproxy.conf.lfsd_file);
2936
Willy Tarreaua534fea2008-08-03 12:19:50 +02002937 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002938 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002939
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 /* we cannot free uri_auth because it might already be used */
2941 init_default_instance();
2942 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002943 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2944 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 }
2948 else if (curproxy == NULL) {
2949 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002953
2954 /* update the current file and line being parsed */
2955 curproxy->conf.args.file = curproxy->conf.file;
2956 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002957
2958 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002959 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2960 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2961 if (err_code & ERR_FATAL)
2962 goto out;
2963 }
2964 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002965 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002966 int cur_arg;
2967
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968 if (curproxy == &defproxy) {
2969 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002973 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975
Willy Tarreau24709282013-03-10 21:32:12 +01002976 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002977 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002982
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002983 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002984
2985 /* use default settings for unix sockets */
2986 bind_conf->ux.uid = global.unix_bind.ux.uid;
2987 bind_conf->ux.gid = global.unix_bind.ux.gid;
2988 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002989
2990 /* NOTE: the following line might create several listeners if there
2991 * are comma-separated IPs or port ranges. So all further processing
2992 * will have to be applied to all listeners created after last_listen.
2993 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002994 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2995 if (errmsg && *errmsg) {
2996 indent_msg(&errmsg, 2);
2997 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002998 }
2999 else
3000 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3001 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003005
Willy Tarreau4348fad2012-09-20 16:48:07 +02003006 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3007 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003008 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003009 }
3010
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003011 cur_arg = 2;
3012 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003013 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003014 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003015 char *err;
3016
Willy Tarreau26982662012-09-12 23:17:10 +02003017 kw = bind_find_kw(args[cur_arg]);
3018 if (kw) {
3019 char *err = NULL;
3020 int code;
3021
3022 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003023 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3024 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003025 cur_arg += 1 + kw->skip ;
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029
Willy Tarreau4348fad2012-09-20 16:48:07 +02003030 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003031 err_code |= code;
3032
3033 if (code) {
3034 if (err && *err) {
3035 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003036 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003037 }
3038 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003039 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3040 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003041 if (code & ERR_FATAL) {
3042 free(err);
3043 cur_arg += 1 + kw->skip;
3044 goto out;
3045 }
3046 }
3047 free(err);
3048 cur_arg += 1 + kw->skip;
3049 continue;
3050 }
3051
Willy Tarreau8638f482012-09-18 18:01:17 +02003052 err = NULL;
3053 if (!bind_dumped) {
3054 bind_dump_kws(&err);
3055 indent_msg(&err, 4);
3056 bind_dumped = 1;
3057 }
3058
3059 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3060 file, linenum, args[0], args[1], args[cur_arg],
3061 err ? " Registered keywords :" : "", err ? err : "");
3062 free(err);
3063
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003066 }
Willy Tarreau93893792009-07-23 13:19:11 +02003067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 }
3069 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003070 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3072 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003076 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003078
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 /* flush useless bits */
3080 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003083 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003084 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003086
William Lallemanddf1425a2015-04-28 20:17:49 +02003087 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3088 goto out;
3089
Willy Tarreau1c47f852006-07-09 08:22:27 +02003090 if (!*args[1]) {
3091 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003095 }
3096
Willy Tarreaua534fea2008-08-03 12:19:50 +02003097 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003098 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003099 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003100 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003101 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3102
Willy Tarreau93893792009-07-23 13:19:11 +02003103 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003104 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003106 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3107 goto out;
3108
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3110 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3111 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3112 else {
3113 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
3117 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003118 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003119 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003120
3121 if (curproxy == &defproxy) {
3122 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003126 }
3127
William Lallemanddf1425a2015-04-28 20:17:49 +02003128 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3129 goto out;
3130
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003131 if (!*args[1]) {
3132 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3133 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003136 }
3137
3138 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003139 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003140 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003141
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003142 if (curproxy->uuid <= 0) {
3143 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003144 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003147 }
3148
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003149 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3150 if (node) {
3151 struct proxy *target = container_of(node, struct proxy, conf.id);
3152 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3153 file, linenum, proxy_type_str(curproxy), curproxy->id,
3154 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003159 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003160 else if (!strcmp(args[0], "description")) {
3161 int i, len=0;
3162 char *d;
3163
Cyril Bonté99ed3272010-01-24 23:29:44 +01003164 if (curproxy == &defproxy) {
3165 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3166 file, linenum, args[0]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003171 if (!*args[1]) {
3172 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3173 file, linenum, args[0]);
3174 return -1;
3175 }
3176
Willy Tarreau348acfe2014-04-14 15:00:39 +02003177 for (i = 1; *args[i]; i++)
3178 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003179
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003180 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003181 curproxy->desc = d;
3182
Willy Tarreau348acfe2014-04-14 15:00:39 +02003183 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3184 for (i = 2; *args[i]; i++)
3185 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003186
3187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003189 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 curproxy->state = PR_STSTOPPED;
3192 }
3193 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003194 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 curproxy->state = PR_STNEW;
3197 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003198 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3199 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003200 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003201
3202 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003203 unsigned int low, high;
3204
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003205 if (strcmp(args[cur_arg], "all") == 0) {
3206 set = 0;
3207 break;
3208 }
3209 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003210 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003211 }
3212 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003213 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003214 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003215 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003216 char *dash = strchr(args[cur_arg], '-');
3217
3218 low = high = str2uic(args[cur_arg]);
3219 if (dash)
3220 high = str2uic(dash + 1);
3221
3222 if (high < low) {
3223 unsigned int swap = low;
3224 low = high;
3225 high = swap;
3226 }
3227
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003228 if (low < 1 || high > LONGBITS) {
3229 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3230 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_ALERT | ERR_FATAL;
3232 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003233 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003234 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003235 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003236 }
3237 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003238 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3239 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003242 }
3243 cur_arg++;
3244 }
3245 curproxy->bind_proc = set;
3246 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003247 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003248 if (curproxy == &defproxy) {
3249 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003252 }
3253
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003254 err = invalid_char(args[1]);
3255 if (err) {
3256 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3257 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003259 }
3260
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003261 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003262 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3263 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003266 }
3267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3269 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270
Willy Tarreau977b8e42006-12-29 14:19:17 +01003271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003273
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 if (*(args[1]) == 0) {
3275 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003280
Willy Tarreau67402132012-05-31 20:40:20 +02003281 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003282 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003283 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003284 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 curproxy->cookie_name = strdup(args[1]);
3286 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003287
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 cur_arg = 2;
3289 while (*(args[cur_arg])) {
3290 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003291 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003294 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
3296 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003297 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
3299 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003300 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
3302 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003303 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003305 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003306 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003309 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003311 else if (!strcmp(args[cur_arg], "httponly")) {
3312 curproxy->ck_opts |= PR_CK_HTTPONLY;
3313 }
3314 else if (!strcmp(args[cur_arg], "secure")) {
3315 curproxy->ck_opts |= PR_CK_SECURE;
3316 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003317 else if (!strcmp(args[cur_arg], "domain")) {
3318 if (!*args[cur_arg + 1]) {
3319 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3320 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003323 }
3324
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003325 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003326 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003327 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3328 " dots nor does not start with a dot."
3329 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003330 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003331 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003332 }
3333
3334 err = invalid_domainchar(args[cur_arg + 1]);
3335 if (err) {
3336 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3337 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003340 }
3341
Willy Tarreau68a897b2009-12-03 23:28:34 +01003342 if (!curproxy->cookie_domain) {
3343 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3344 } else {
3345 /* one domain was already specified, add another one by
3346 * building the string which will be returned along with
3347 * the cookie.
3348 */
3349 char *new_ptr;
3350 int new_len = strlen(curproxy->cookie_domain) +
3351 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3352 new_ptr = malloc(new_len);
3353 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3354 free(curproxy->cookie_domain);
3355 curproxy->cookie_domain = new_ptr;
3356 }
Willy Tarreau31936852010-10-06 16:59:56 +02003357 cur_arg++;
3358 }
3359 else if (!strcmp(args[cur_arg], "maxidle")) {
3360 unsigned int maxidle;
3361 const char *res;
3362
3363 if (!*args[cur_arg + 1]) {
3364 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3365 file, linenum, args[cur_arg]);
3366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
3368 }
3369
3370 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3371 if (res) {
3372 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3373 file, linenum, *res, args[cur_arg]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377 curproxy->cookie_maxidle = maxidle;
3378 cur_arg++;
3379 }
3380 else if (!strcmp(args[cur_arg], "maxlife")) {
3381 unsigned int maxlife;
3382 const char *res;
3383
3384 if (!*args[cur_arg + 1]) {
3385 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3386 file, linenum, args[cur_arg]);
3387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
3389 }
3390
3391 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3392 if (res) {
3393 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3394 file, linenum, *res, args[cur_arg]);
3395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
3397 }
3398 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003399 cur_arg++;
3400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003402 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 +02003403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003404 err_code |= ERR_ALERT | ERR_FATAL;
3405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
3407 cur_arg++;
3408 }
Willy Tarreau67402132012-05-31 20:40:20 +02003409 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3411 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 }
3414
Willy Tarreau67402132012-05-31 20:40:20 +02003415 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3417 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003418 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003420
Willy Tarreau67402132012-05-31 20:40:20 +02003421 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003422 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3423 file, linenum);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003427 else if (!strcmp(args[0], "email-alert")) {
3428 if (*(args[1]) == 0) {
3429 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3430 file, linenum, args[0]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
3433 }
3434
3435 if (!strcmp(args[1], "from")) {
3436 if (*(args[1]) == 0) {
3437 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3438 file, linenum, args[1]);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
3442 free(curproxy->email_alert.from);
3443 curproxy->email_alert.from = strdup(args[2]);
3444 }
3445 else if (!strcmp(args[1], "mailers")) {
3446 if (*(args[1]) == 0) {
3447 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3448 file, linenum, args[1]);
3449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
3451 }
3452 free(curproxy->email_alert.mailers.name);
3453 curproxy->email_alert.mailers.name = strdup(args[2]);
3454 }
3455 else if (!strcmp(args[1], "myhostname")) {
3456 if (*(args[1]) == 0) {
3457 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3458 file, linenum, args[1]);
3459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
3462 free(curproxy->email_alert.myhostname);
3463 curproxy->email_alert.myhostname = strdup(args[2]);
3464 }
Simon Horman64e34162015-02-06 11:11:57 +09003465 else if (!strcmp(args[1], "level")) {
3466 curproxy->email_alert.level = get_log_level(args[2]);
3467 if (curproxy->email_alert.level < 0) {
3468 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3469 file, linenum, args[1], args[2]);
3470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
3472 }
3473 }
Simon Horman9dc49962015-01-30 11:22:59 +09003474 else if (!strcmp(args[1], "to")) {
3475 if (*(args[1]) == 0) {
3476 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3477 file, linenum, args[1]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
3481 free(curproxy->email_alert.to);
3482 curproxy->email_alert.to = strdup(args[2]);
3483 }
3484 else {
3485 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3486 file, linenum, args[1]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
Simon Horman64e34162015-02-06 11:11:57 +09003490 /* Indicate that the email_alert is at least partially configured */
3491 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003492 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003493 else if (!strcmp(args[0], "external-check")) {
3494 if (*(args[1]) == 0) {
3495 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3496 file, linenum, args[0]);
3497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500
3501 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003502 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003503 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003504 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003505 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3506 file, linenum, args[1]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
3510 free(curproxy->check_command);
3511 curproxy->check_command = strdup(args[2]);
3512 }
3513 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003514 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003515 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003516 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003517 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3518 file, linenum, args[1]);
3519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
3521 }
3522 free(curproxy->check_path);
3523 curproxy->check_path = strdup(args[2]);
3524 }
3525 else {
3526 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3527 file, linenum, args[1]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003532 else if (!strcmp(args[0], "persist")) { /* persist */
3533 if (*(args[1]) == 0) {
3534 Alert("parsing [%s:%d] : missing persist method.\n",
3535 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003538 }
3539
3540 if (!strncmp(args[1], "rdp-cookie", 10)) {
3541 curproxy->options2 |= PR_O2_RDPC_PRST;
3542
Emeric Brunb982a3d2010-01-04 15:45:53 +01003543 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003544 const char *beg, *end;
3545
3546 beg = args[1] + 11;
3547 end = strchr(beg, ')');
3548
William Lallemanddf1425a2015-04-28 20:17:49 +02003549 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3550 goto out;
3551
Emeric Brun647caf12009-06-30 17:57:00 +02003552 if (!end || end == beg) {
3553 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3554 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003557 }
3558
3559 free(curproxy->rdp_cookie_name);
3560 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3561 curproxy->rdp_cookie_len = end-beg;
3562 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003563 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003564 free(curproxy->rdp_cookie_name);
3565 curproxy->rdp_cookie_name = strdup("msts");
3566 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3567 }
3568 else { /* syntax */
3569 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3570 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003573 }
3574 }
3575 else {
3576 Alert("parsing [%s:%d] : unknown persist method.\n",
3577 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003580 }
3581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003583 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003587 else if (!strcmp(args[0], "load-server-state-from-file")) {
3588 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3589 err_code |= ERR_WARN;
3590 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3591 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3592 }
3593 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3594 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3595 }
3596 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3597 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3598 }
3599 else {
3600 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3601 file, linenum, args[0], args[1]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605 }
3606 else if (!strcmp(args[0], "server-state-file-name")) {
3607 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3608 err_code |= ERR_WARN;
3609 if (*(args[1]) == 0) {
3610 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3611 file, linenum, args[0]);
3612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
3614 }
3615 else if (!strcmp(args[1], "use-backend-name"))
3616 curproxy->server_state_file_name = strdup(curproxy->id);
3617 else
3618 curproxy->server_state_file_name = strdup(args[1]);
3619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003620 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003621 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003623
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003625 if (curproxy == &defproxy) {
3626 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
3629 }
3630
William Lallemand1a748ae2015-05-19 16:37:23 +02003631 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3632 goto out;
3633
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 if (*(args[4]) == 0) {
3635 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003640 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 curproxy->capture_name = strdup(args[2]);
3642 curproxy->capture_namelen = strlen(curproxy->capture_name);
3643 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 curproxy->to_log |= LW_COOKIE;
3645 }
3646 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3647 struct cap_hdr *hdr;
3648
3649 if (curproxy == &defproxy) {
3650 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 +02003651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 }
3654
William Lallemand1a748ae2015-05-19 16:37:23 +02003655 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3656 goto out;
3657
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3659 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3660 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 }
3664
Vincent Bernat02779b62016-04-03 13:48:43 +02003665 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 hdr->next = curproxy->req_cap;
3667 hdr->name = strdup(args[3]);
3668 hdr->namelen = strlen(args[3]);
3669 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003670 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 hdr->index = curproxy->nb_req_cap++;
3672 curproxy->req_cap = hdr;
3673 curproxy->to_log |= LW_REQHDR;
3674 }
3675 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3676 struct cap_hdr *hdr;
3677
3678 if (curproxy == &defproxy) {
3679 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 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
3683
William Lallemand1a748ae2015-05-19 16:37:23 +02003684 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3685 goto out;
3686
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3688 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3689 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003693 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 hdr->next = curproxy->rsp_cap;
3695 hdr->name = strdup(args[3]);
3696 hdr->namelen = strlen(args[3]);
3697 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003698 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 hdr->index = curproxy->nb_rsp_cap++;
3700 curproxy->rsp_cap = hdr;
3701 curproxy->to_log |= LW_RSPHDR;
3702 }
3703 else {
3704 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3705 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
3709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003713
William Lallemanddf1425a2015-04-28 20:17:49 +02003714 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3715 goto out;
3716
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 if (*(args[1]) == 0) {
3718 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3719 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 }
3723 curproxy->conn_retries = atol(args[1]);
3724 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003725 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003726 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003727
3728 if (curproxy == &defproxy) {
3729 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733
Willy Tarreau20b0de52012-12-24 15:45:22 +01003734 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003735 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003736 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3737 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3738 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3739 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003740 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 +01003741 file, linenum, args[0]);
3742 err_code |= ERR_WARN;
3743 }
3744
Willy Tarreauff011f22011-01-06 17:51:27 +01003745 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003746
Willy Tarreauff011f22011-01-06 17:51:27 +01003747 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003748 err_code |= ERR_ALERT | ERR_ABORT;
3749 goto out;
3750 }
3751
Willy Tarreau5002f572014-04-23 01:32:02 +02003752 err_code |= warnif_misplaced_http_req(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);
3756
Willy Tarreauff011f22011-01-06 17:51:27 +01003757 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003758 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003759 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003760 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003761
3762 if (curproxy == &defproxy) {
3763 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
3767
3768 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003769 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003770 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3771 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003772 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3773 file, linenum, args[0]);
3774 err_code |= ERR_WARN;
3775 }
3776
3777 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3778
3779 if (!rule) {
3780 err_code |= ERR_ALERT | ERR_ABORT;
3781 goto out;
3782 }
3783
3784 err_code |= warnif_cond_conflicts(rule->cond,
3785 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3786 file, linenum);
3787
3788 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3789 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003790 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3791 /* set the header name and length into the proxy structure */
3792 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3793 err_code |= ERR_WARN;
3794
3795 if (!*args[1]) {
3796 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3797 file, linenum, args[0]);
3798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
3800 }
3801
3802 /* set the desired header name */
3803 free(curproxy->server_id_hdr_name);
3804 curproxy->server_id_hdr_name = strdup(args[1]);
3805 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3806 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003807 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003808 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003809
Willy Tarreaub099aca2008-10-12 17:26:37 +02003810 if (curproxy == &defproxy) {
3811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003814 }
3815
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003816 /* emulate "block" using "http-request block". Since these rules are supposed to
3817 * be processed before all http-request rules, we put them into their own list
3818 * and will insert them at the end.
3819 */
3820 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3821 if (!rule) {
3822 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003823 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003824 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003825 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3826 err_code |= warnif_cond_conflicts(rule->cond,
3827 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3828 file, linenum);
3829 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003830
3831 if (!already_warned(WARN_BLOCK_DEPRECATED))
3832 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]);
3833
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003834 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003835 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003836 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003837
Cyril Bonté99ed3272010-01-24 23:29:44 +01003838 if (curproxy == &defproxy) {
3839 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843
Willy Tarreaube4653b2015-05-28 15:26:58 +02003844 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003845 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3846 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003849 }
3850
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003851 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003852 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003853 err_code |= warnif_cond_conflicts(rule->cond,
3854 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3855 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003856 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003857 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003858 struct switching_rule *rule;
3859
Willy Tarreaub099aca2008-10-12 17:26:37 +02003860 if (curproxy == &defproxy) {
3861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003864 }
3865
Willy Tarreau55ea7572007-06-17 19:56:27 +02003866 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003868
3869 if (*(args[1]) == 0) {
3870 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003873 }
3874
Willy Tarreauf51658d2014-04-23 01:21:56 +02003875 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3876 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3877 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3878 file, linenum, errmsg);
3879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
3881 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003882
Willy Tarreauf51658d2014-04-23 01:21:56 +02003883 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003884 }
3885
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003886 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003887 if (!rule) {
3888 Alert("Out of memory error.\n");
3889 goto out;
3890 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003891 rule->cond = cond;
3892 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003893 rule->line = linenum;
3894 rule->file = strdup(file);
3895 if (!rule->file) {
3896 Alert("Out of memory error.\n");
3897 goto out;
3898 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003899 LIST_INIT(&rule->list);
3900 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3901 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003902 else if (strcmp(args[0], "use-server") == 0) {
3903 struct server_rule *rule;
3904
3905 if (curproxy == &defproxy) {
3906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
3910
3911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3912 err_code |= ERR_WARN;
3913
3914 if (*(args[1]) == 0) {
3915 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918 }
3919
3920 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3921 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3922 file, linenum, args[0]);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925 }
3926
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003927 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3928 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3929 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
3932 }
3933
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003934 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003935
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003936 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003937 rule->cond = cond;
3938 rule->srv.name = strdup(args[1]);
3939 LIST_INIT(&rule->list);
3940 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3941 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3942 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003943 else if ((!strcmp(args[0], "force-persist")) ||
3944 (!strcmp(args[0], "ignore-persist"))) {
3945 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003946
3947 if (curproxy == &defproxy) {
3948 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
3951 }
3952
3953 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3954 err_code |= ERR_WARN;
3955
Willy Tarreauef6494c2010-01-28 17:12:36 +01003956 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003957 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3958 file, linenum, args[0]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003963 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3964 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3965 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003970 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3971 * where force-persist is applied.
3972 */
3973 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003974
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003975 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003976 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003977 if (!strcmp(args[0], "force-persist")) {
3978 rule->type = PERSIST_TYPE_FORCE;
3979 } else {
3980 rule->type = PERSIST_TYPE_IGNORE;
3981 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003982 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003983 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003984 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003985 else if (!strcmp(args[0], "stick-table")) {
3986 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003987 struct proxy *other;
3988
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003989 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003990 if (other) {
3991 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3992 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003996
Emeric Brun32da3c42010-09-23 18:39:19 +02003997 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003998 curproxy->table.type = (unsigned int)-1;
3999 while (*args[myidx]) {
4000 const char *err;
4001
4002 if (strcmp(args[myidx], "size") == 0) {
4003 myidx++;
4004 if (!*(args[myidx])) {
4005 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4006 file, linenum, args[myidx-1]);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
4010 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4011 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4012 file, linenum, *err, args[myidx-1]);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004016 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004017 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004018 else if (strcmp(args[myidx], "peers") == 0) {
4019 myidx++;
Godbach50523162013-12-11 19:48:57 +08004020 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004021 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4022 file, linenum, args[myidx-1]);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
Godbach50523162013-12-11 19:48:57 +08004025 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004026 curproxy->table.peers.name = strdup(args[myidx++]);
4027 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004028 else if (strcmp(args[myidx], "expire") == 0) {
4029 myidx++;
4030 if (!*(args[myidx])) {
4031 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4032 file, linenum, args[myidx-1]);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4037 if (err) {
4038 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4039 file, linenum, *err, args[myidx-1]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004043 if (val > INT_MAX) {
4044 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4045 file, linenum, val);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004049 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004050 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004051 }
4052 else if (strcmp(args[myidx], "nopurge") == 0) {
4053 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004054 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004055 }
4056 else if (strcmp(args[myidx], "type") == 0) {
4057 myidx++;
4058 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4059 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4060 file, linenum, args[myidx]);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004064 /* myidx already points to next arg */
4065 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004066 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004067 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004068 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004069
4070 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004071 nw = args[myidx];
4072 while (*nw) {
4073 /* the "store" keyword supports a comma-separated list */
4074 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004075 sa = NULL; /* store arg */
4076 while (*nw && *nw != ',') {
4077 if (*nw == '(') {
4078 *nw = 0;
4079 sa = ++nw;
4080 while (*nw != ')') {
4081 if (!*nw) {
4082 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4083 file, linenum, args[0], cw);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087 nw++;
4088 }
4089 *nw = '\0';
4090 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004091 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004092 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004093 if (*nw)
4094 *nw++ = '\0';
4095 type = stktable_get_data_type(cw);
4096 if (type < 0) {
4097 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4098 file, linenum, args[0], cw);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
Willy Tarreauac782882010-06-20 10:41:54 +02004102
4103 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4104 switch (err) {
4105 case PE_NONE: break;
4106 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004107 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4108 file, linenum, args[0], cw);
4109 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004110 break;
4111
4112 case PE_ARG_MISSING:
4113 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4114 file, linenum, args[0], cw);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117
4118 case PE_ARG_NOT_USED:
4119 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4120 file, linenum, args[0], cw);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
4123
4124 default:
4125 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4126 file, linenum, args[0], cw);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004129 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004130 }
4131 myidx++;
4132 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004133 else {
4134 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4135 file, linenum, args[myidx]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004138 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004139 }
4140
4141 if (!curproxy->table.size) {
4142 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4143 file, linenum);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147
4148 if (curproxy->table.type == (unsigned int)-1) {
4149 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4150 file, linenum);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154 }
4155 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004157 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 int myidx = 0;
4159 const char *name = NULL;
4160 int flags;
4161
4162 if (curproxy == &defproxy) {
4163 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
4167
4168 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4169 err_code |= ERR_WARN;
4170 goto out;
4171 }
4172
4173 myidx++;
4174 if ((strcmp(args[myidx], "store") == 0) ||
4175 (strcmp(args[myidx], "store-request") == 0)) {
4176 myidx++;
4177 flags = STK_IS_STORE;
4178 }
4179 else if (strcmp(args[myidx], "store-response") == 0) {
4180 myidx++;
4181 flags = STK_IS_STORE | STK_ON_RSP;
4182 }
4183 else if (strcmp(args[myidx], "match") == 0) {
4184 myidx++;
4185 flags = STK_IS_MATCH;
4186 }
4187 else if (strcmp(args[myidx], "on") == 0) {
4188 myidx++;
4189 flags = STK_IS_MATCH | STK_IS_STORE;
4190 }
4191 else {
4192 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196
4197 if (*(args[myidx]) == 0) {
4198 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
4202
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004203 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004204 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004205 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004206 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
4209 }
4210
4211 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004212 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4213 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4214 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004215 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004216 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004217 goto out;
4218 }
4219 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004220 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4221 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4222 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004223 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004224 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004225 goto out;
4226 }
4227 }
4228
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004229 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004230 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004231
Emeric Brunb982a3d2010-01-04 15:45:53 +01004232 if (strcmp(args[myidx], "table") == 0) {
4233 myidx++;
4234 name = args[myidx++];
4235 }
4236
Willy Tarreauef6494c2010-01-28 17:12:36 +01004237 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004238 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4239 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4240 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004241 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004242 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004243 goto out;
4244 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004245 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004246 else if (*(args[myidx])) {
4247 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4248 file, linenum, args[0], args[myidx]);
4249 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004250 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004251 goto out;
4252 }
Emeric Brun97679e72010-09-23 17:56:44 +02004253 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004254 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004255 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004256 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004257
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004258 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004259 rule->cond = cond;
4260 rule->expr = expr;
4261 rule->flags = flags;
4262 rule->table.name = name ? strdup(name) : NULL;
4263 LIST_INIT(&rule->list);
4264 if (flags & STK_ON_RSP)
4265 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4266 else
4267 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 else if (!strcmp(args[0], "stats")) {
4270 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4271 curproxy->uri_auth = NULL; /* we must detach from the default config */
4272
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004273 if (!*args[1]) {
4274 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004275 } else if (!strcmp(args[1], "admin")) {
4276 struct stats_admin_rule *rule;
4277
4278 if (curproxy == &defproxy) {
4279 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283
4284 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4285 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4286 err_code |= ERR_ALERT | ERR_ABORT;
4287 goto out;
4288 }
4289
4290 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4291 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4292 file, linenum, args[0], args[1]);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004296 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4297 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4298 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004303 err_code |= warnif_cond_conflicts(cond,
4304 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4305 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004306
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004307 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004308 rule->cond = cond;
4309 LIST_INIT(&rule->list);
4310 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 } else if (!strcmp(args[1], "uri")) {
4312 if (*(args[2]) == 0) {
4313 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4317 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_ABORT;
4319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 }
4321 } else if (!strcmp(args[1], "realm")) {
4322 if (*(args[2]) == 0) {
4323 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004326 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_ABORT;
4329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004331 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004332 unsigned interval;
4333
4334 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4335 if (err) {
4336 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4337 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004340 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4341 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004342 err_code |= ERR_ALERT | ERR_ABORT;
4343 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004344 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004345 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004346 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004347
4348 if (curproxy == &defproxy) {
4349 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353
4354 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4355 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4356 err_code |= ERR_ALERT | ERR_ABORT;
4357 goto out;
4358 }
4359
Willy Tarreauff011f22011-01-06 17:51:27 +01004360 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004361 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004362 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4363 file, linenum, args[0]);
4364 err_code |= ERR_WARN;
4365 }
4366
Willy Tarreauff011f22011-01-06 17:51:27 +01004367 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004368
Willy Tarreauff011f22011-01-06 17:51:27 +01004369 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004370 err_code |= ERR_ALERT | ERR_ABORT;
4371 goto out;
4372 }
4373
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004374 err_code |= warnif_cond_conflicts(rule->cond,
4375 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4376 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004377 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004378
Willy Tarreaubaaee002006-06-26 02:48:02 +02004379 } else if (!strcmp(args[1], "auth")) {
4380 if (*(args[2]) == 0) {
4381 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4385 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 }
4389 } else if (!strcmp(args[1], "scope")) {
4390 if (*(args[2]) == 0) {
4391 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4395 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_ABORT;
4397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 }
4399 } else if (!strcmp(args[1], "enable")) {
4400 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4401 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_ABORT;
4403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004405 } else if (!strcmp(args[1], "hide-version")) {
4406 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4407 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_ABORT;
4409 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004410 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004411 } else if (!strcmp(args[1], "show-legends")) {
4412 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4413 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4414 err_code |= ERR_ALERT | ERR_ABORT;
4415 goto out;
4416 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004417 } else if (!strcmp(args[1], "show-node")) {
4418
4419 if (*args[2]) {
4420 int i;
4421 char c;
4422
4423 for (i=0; args[2][i]; i++) {
4424 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004425 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4426 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004427 break;
4428 }
4429
4430 if (!i || args[2][i]) {
4431 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4432 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4433 file, linenum, args[0], args[1]);
4434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
4436 }
4437 }
4438
4439 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4440 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4441 err_code |= ERR_ALERT | ERR_ABORT;
4442 goto out;
4443 }
4444 } else if (!strcmp(args[1], "show-desc")) {
4445 char *desc = NULL;
4446
4447 if (*args[2]) {
4448 int i, len=0;
4449 char *d;
4450
Willy Tarreau348acfe2014-04-14 15:00:39 +02004451 for (i = 2; *args[i]; i++)
4452 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004453
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004454 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004455
Willy Tarreau348acfe2014-04-14 15:00:39 +02004456 d += snprintf(d, desc + len - d, "%s", args[2]);
4457 for (i = 3; *args[i]; i++)
4458 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004459 }
4460
4461 if (!*args[2] && !global.desc)
4462 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4463 file, linenum, args[1]);
4464 else {
4465 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4466 free(desc);
4467 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4468 err_code |= ERR_ALERT | ERR_ABORT;
4469 goto out;
4470 }
4471 free(desc);
4472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004474stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004475 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004476 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 }
4480 }
4481 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004482 int optnum;
4483
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004484 if (*(args[1]) == '\0') {
4485 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4486 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004490
4491 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4492 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004493 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4494 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4495 file, linenum, cfg_opts[optnum].name);
4496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
4498 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004499 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4500 goto out;
4501
Willy Tarreau93893792009-07-23 13:19:11 +02004502 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4503 err_code |= ERR_WARN;
4504 goto out;
4505 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004506
Willy Tarreau3842f002009-06-14 11:39:52 +02004507 curproxy->no_options &= ~cfg_opts[optnum].val;
4508 curproxy->options &= ~cfg_opts[optnum].val;
4509
4510 switch (kwm) {
4511 case KWM_STD:
4512 curproxy->options |= cfg_opts[optnum].val;
4513 break;
4514 case KWM_NO:
4515 curproxy->no_options |= cfg_opts[optnum].val;
4516 break;
4517 case KWM_DEF: /* already cleared */
4518 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004519 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004520
Willy Tarreau93893792009-07-23 13:19:11 +02004521 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004522 }
4523 }
4524
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004525 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4526 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004527 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4528 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4529 file, linenum, cfg_opts2[optnum].name);
4530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
4532 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004533 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4534 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004535 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4536 err_code |= ERR_WARN;
4537 goto out;
4538 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004539
Willy Tarreau3842f002009-06-14 11:39:52 +02004540 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4541 curproxy->options2 &= ~cfg_opts2[optnum].val;
4542
4543 switch (kwm) {
4544 case KWM_STD:
4545 curproxy->options2 |= cfg_opts2[optnum].val;
4546 break;
4547 case KWM_NO:
4548 curproxy->no_options2 |= cfg_opts2[optnum].val;
4549 break;
4550 case KWM_DEF: /* already cleared */
4551 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004552 }
Willy Tarreau93893792009-07-23 13:19:11 +02004553 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004554 }
4555 }
4556
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004557 /* HTTP options override each other. They can be cancelled using
4558 * "no option xxx" which only switches to default mode if the mode
4559 * was this one (useful for cancelling options set in defaults
4560 * sections).
4561 */
4562 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004563 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4564 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004565 if (kwm == KWM_STD) {
4566 curproxy->options &= ~PR_O_HTTP_MODE;
4567 curproxy->options |= PR_O_HTTP_PCL;
4568 goto out;
4569 }
4570 else if (kwm == KWM_NO) {
4571 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4572 curproxy->options &= ~PR_O_HTTP_MODE;
4573 goto out;
4574 }
4575 }
4576 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004577 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4578 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004579 if (kwm == KWM_STD) {
4580 curproxy->options &= ~PR_O_HTTP_MODE;
4581 curproxy->options |= PR_O_HTTP_FCL;
4582 goto out;
4583 }
4584 else if (kwm == KWM_NO) {
4585 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4586 curproxy->options &= ~PR_O_HTTP_MODE;
4587 goto out;
4588 }
4589 }
4590 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004591 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4592 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004593 if (kwm == KWM_STD) {
4594 curproxy->options &= ~PR_O_HTTP_MODE;
4595 curproxy->options |= PR_O_HTTP_SCL;
4596 goto out;
4597 }
4598 else if (kwm == KWM_NO) {
4599 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4600 curproxy->options &= ~PR_O_HTTP_MODE;
4601 goto out;
4602 }
4603 }
4604 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004605 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4606 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004607 if (kwm == KWM_STD) {
4608 curproxy->options &= ~PR_O_HTTP_MODE;
4609 curproxy->options |= PR_O_HTTP_KAL;
4610 goto out;
4611 }
4612 else if (kwm == KWM_NO) {
4613 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4614 curproxy->options &= ~PR_O_HTTP_MODE;
4615 goto out;
4616 }
4617 }
4618 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004619 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4620 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004621 if (kwm == KWM_STD) {
4622 curproxy->options &= ~PR_O_HTTP_MODE;
4623 curproxy->options |= PR_O_HTTP_TUN;
4624 goto out;
4625 }
4626 else if (kwm == KWM_NO) {
4627 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4628 curproxy->options &= ~PR_O_HTTP_MODE;
4629 goto out;
4630 }
4631 }
4632
Joseph Lynch726ab712015-05-11 23:25:34 -07004633 /* Redispatch can take an integer argument that control when the
4634 * resispatch occurs. All values are relative to the retries option.
4635 * This can be cancelled using "no option xxx".
4636 */
4637 if (strcmp(args[1], "redispatch") == 0) {
4638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4639 err_code |= ERR_WARN;
4640 goto out;
4641 }
4642
4643 curproxy->no_options &= ~PR_O_REDISP;
4644 curproxy->options &= ~PR_O_REDISP;
4645
4646 switch (kwm) {
4647 case KWM_STD:
4648 curproxy->options |= PR_O_REDISP;
4649 curproxy->redispatch_after = -1;
4650 if(*args[2]) {
4651 curproxy->redispatch_after = atol(args[2]);
4652 }
4653 break;
4654 case KWM_NO:
4655 curproxy->no_options |= PR_O_REDISP;
4656 curproxy->redispatch_after = 0;
4657 break;
4658 case KWM_DEF: /* already cleared */
4659 break;
4660 }
4661 goto out;
4662 }
4663
Willy Tarreau3842f002009-06-14 11:39:52 +02004664 if (kwm != KWM_STD) {
4665 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004666 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004669 }
4670
Emeric Brun3a058f32009-06-30 18:26:00 +02004671 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004672 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004674 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004675 if (*(args[2]) != '\0') {
4676 if (!strcmp(args[2], "clf")) {
4677 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004678 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004679 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004680 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004683 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004684 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4685 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004686 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004687 if (curproxy->conf.logformat_string != default_http_log_format &&
4688 curproxy->conf.logformat_string != default_tcp_log_format &&
4689 curproxy->conf.logformat_string != clf_http_log_format)
4690 free(curproxy->conf.logformat_string);
4691 curproxy->conf.logformat_string = logformat;
4692
4693 free(curproxy->conf.lfs_file);
4694 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4695 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004696 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004697 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004699 if (curproxy->conf.logformat_string != default_http_log_format &&
4700 curproxy->conf.logformat_string != default_tcp_log_format &&
4701 curproxy->conf.logformat_string != clf_http_log_format)
4702 free(curproxy->conf.logformat_string);
4703 curproxy->conf.logformat_string = default_tcp_log_format;
4704
4705 free(curproxy->conf.lfs_file);
4706 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4707 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004708
4709 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4710 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004713 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004714 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004716
William Lallemanddf1425a2015-04-28 20:17:49 +02004717 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4718 goto out;
4719
Willy Tarreau13943ab2006-12-31 00:24:10 +01004720 if (curproxy->cap & PR_CAP_FE)
4721 curproxy->options |= PR_O_TCP_CLI_KA;
4722 if (curproxy->cap & PR_CAP_BE)
4723 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 }
4725 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_WARN;
4728
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004730 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004731 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004732 curproxy->options2 &= ~PR_O2_CHK_ANY;
4733 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734 if (!*args[2]) { /* no argument */
4735 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4736 curproxy->check_len = strlen(DEF_CHECK_REQ);
4737 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004738 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004739 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004741 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004743 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 if (*args[4])
4745 reqlen += strlen(args[4]);
4746 else
4747 reqlen += strlen("HTTP/1.0");
4748
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004749 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004751 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004753 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4754 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004755 }
4756 else if (!strcmp(args[1], "ssl-hello-chk")) {
4757 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004759 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004760
Willy Tarreaua534fea2008-08-03 12:19:50 +02004761 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004762 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004763 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004764 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004765
4766 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
Willy Tarreau23677902007-05-08 23:50:35 +02004769 else if (!strcmp(args[1], "smtpchk")) {
4770 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004771 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004772 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004773 curproxy->options2 &= ~PR_O2_CHK_ANY;
4774 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004775
4776 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4777 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4778 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4779 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4780 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4781 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004782 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004783 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4784 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4785 } else {
4786 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4787 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4788 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4789 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4790 }
4791 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004792 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4793 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004794 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004795 else if (!strcmp(args[1], "pgsql-check")) {
4796 /* use PostgreSQL request to check servers' health */
4797 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4798 err_code |= ERR_WARN;
4799
4800 free(curproxy->check_req);
4801 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004802 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004803 curproxy->options2 |= PR_O2_PGSQL_CHK;
4804
4805 if (*(args[2])) {
4806 int cur_arg = 2;
4807
4808 while (*(args[cur_arg])) {
4809 if (strcmp(args[cur_arg], "user") == 0) {
4810 char * packet;
4811 uint32_t packet_len;
4812 uint32_t pv;
4813
4814 /* suboption header - needs additional argument for it */
4815 if (*(args[cur_arg+1]) == 0) {
4816 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4817 file, linenum, args[0], args[1], args[cur_arg]);
4818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 }
4821
4822 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4823 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4824 pv = htonl(0x30000); /* protocol version 3.0 */
4825
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004826 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004827
4828 memcpy(packet + 4, &pv, 4);
4829
4830 /* copy "user" */
4831 memcpy(packet + 8, "user", 4);
4832
4833 /* copy username */
4834 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4835
4836 free(curproxy->check_req);
4837 curproxy->check_req = packet;
4838 curproxy->check_len = packet_len;
4839
4840 packet_len = htonl(packet_len);
4841 memcpy(packet, &packet_len, 4);
4842 cur_arg += 2;
4843 } else {
4844 /* unknown suboption - catchall */
4845 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4846 file, linenum, args[0], args[1]);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
4850 } /* end while loop */
4851 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004852 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4853 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004854 }
4855
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004856 else if (!strcmp(args[1], "redis-check")) {
4857 /* use REDIS PING request to check servers' health */
4858 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4859 err_code |= ERR_WARN;
4860
4861 free(curproxy->check_req);
4862 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004863 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004864 curproxy->options2 |= PR_O2_REDIS_CHK;
4865
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004866 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004867 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4868 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004869
4870 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4871 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004872 }
4873
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004874 else if (!strcmp(args[1], "mysql-check")) {
4875 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4877 err_code |= ERR_WARN;
4878
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004879 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004880 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004881 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004882 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004883
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004884 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004885 * const char mysql40_client_auth_pkt[] = {
4886 * "\x0e\x00\x00" // packet length
4887 * "\x01" // packet number
4888 * "\x00\x00" // client capabilities
4889 * "\x00\x00\x01" // max packet
4890 * "haproxy\x00" // username (null terminated string)
4891 * "\x00" // filler (always 0x00)
4892 * "\x01\x00\x00" // packet length
4893 * "\x00" // packet number
4894 * "\x01" // COM_QUIT command
4895 * };
4896 */
4897
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004898 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4899 * const char mysql41_client_auth_pkt[] = {
4900 * "\x0e\x00\x00\" // packet length
4901 * "\x01" // packet number
4902 * "\x00\x00\x00\x00" // client capabilities
4903 * "\x00\x00\x00\x01" // max packet
4904 * "\x21" // character set (UTF-8)
4905 * char[23] // All zeroes
4906 * "haproxy\x00" // username (null terminated string)
4907 * "\x00" // filler (always 0x00)
4908 * "\x01\x00\x00" // packet length
4909 * "\x00" // packet number
4910 * "\x01" // COM_QUIT command
4911 * };
4912 */
4913
4914
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004915 if (*(args[2])) {
4916 int cur_arg = 2;
4917
4918 while (*(args[cur_arg])) {
4919 if (strcmp(args[cur_arg], "user") == 0) {
4920 char *mysqluser;
4921 int packetlen, reqlen, userlen;
4922
4923 /* suboption header - needs additional argument for it */
4924 if (*(args[cur_arg+1]) == 0) {
4925 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4926 file, linenum, args[0], args[1], args[cur_arg]);
4927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
4929 }
4930 mysqluser = args[cur_arg + 1];
4931 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004932
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004933 if (*(args[cur_arg+2])) {
4934 if (!strcmp(args[cur_arg+2], "post-41")) {
4935 packetlen = userlen + 7 + 27;
4936 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004937
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004938 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004939 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004940 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004941
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004942 snprintf(curproxy->check_req, 4, "%c%c%c",
4943 ((unsigned char) packetlen & 0xff),
4944 ((unsigned char) (packetlen >> 8) & 0xff),
4945 ((unsigned char) (packetlen >> 16) & 0xff));
4946
4947 curproxy->check_req[3] = 1;
4948 curproxy->check_req[5] = 130;
4949 curproxy->check_req[11] = 1;
4950 curproxy->check_req[12] = 33;
4951 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4952 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4953 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4954 cur_arg += 3;
4955 } else {
4956 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
4959 }
4960 } else {
4961 packetlen = userlen + 7;
4962 reqlen = packetlen + 9;
4963
4964 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004965 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004966 curproxy->check_len = reqlen;
4967
4968 snprintf(curproxy->check_req, 4, "%c%c%c",
4969 ((unsigned char) packetlen & 0xff),
4970 ((unsigned char) (packetlen >> 8) & 0xff),
4971 ((unsigned char) (packetlen >> 16) & 0xff));
4972
4973 curproxy->check_req[3] = 1;
4974 curproxy->check_req[5] = 128;
4975 curproxy->check_req[8] = 1;
4976 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4977 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4978 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4979 cur_arg += 2;
4980 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004981 } else {
4982 /* unknown suboption - catchall */
4983 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4984 file, linenum, args[0], args[1]);
4985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988 } /* end while loop */
4989 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004990 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004991 else if (!strcmp(args[1], "ldap-check")) {
4992 /* use LDAP request to check servers' health */
4993 free(curproxy->check_req);
4994 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004995 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004996 curproxy->options2 |= PR_O2_LDAP_CHK;
4997
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004998 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004999 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5000 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005001 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5002 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005003 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005004 else if (!strcmp(args[1], "spop-check")) {
5005 if (curproxy == &defproxy) {
5006 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5007 file, linenum, args[0], args[1]);
5008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010 }
5011 if (curproxy->cap & PR_CAP_FE) {
5012 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5013 file, linenum, args[0], args[1]);
5014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
5016 }
5017
5018 /* use SPOE request to check servers' health */
5019 free(curproxy->check_req);
5020 curproxy->check_req = NULL;
5021 curproxy->options2 &= ~PR_O2_CHK_ANY;
5022 curproxy->options2 |= PR_O2_SPOP_CHK;
5023
5024 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
5025 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
5028 }
5029 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5030 goto out;
5031 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005032 else if (!strcmp(args[1], "tcp-check")) {
5033 /* use raw TCPCHK send/expect to check servers' health */
5034 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5035 err_code |= ERR_WARN;
5036
5037 free(curproxy->check_req);
5038 curproxy->check_req = NULL;
5039 curproxy->options2 &= ~PR_O2_CHK_ANY;
5040 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005041 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5042 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005043 }
Simon Horman98637e52014-06-20 12:30:16 +09005044 else if (!strcmp(args[1], "external-check")) {
5045 /* excute an external command to check servers' health */
5046 free(curproxy->check_req);
5047 curproxy->check_req = NULL;
5048 curproxy->options2 &= ~PR_O2_CHK_ANY;
5049 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005050 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5051 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005052 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005053 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005054 int cur_arg;
5055
5056 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5057 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005058 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005059
Willy Tarreau87cf5142011-08-19 22:57:24 +02005060 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005061
5062 free(curproxy->fwdfor_hdr_name);
5063 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5064 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5065
5066 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5067 cur_arg = 2;
5068 while (*(args[cur_arg])) {
5069 if (!strcmp(args[cur_arg], "except")) {
5070 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005071 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005072 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5073 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005076 }
5077 /* flush useless bits */
5078 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005079 cur_arg += 2;
5080 } else if (!strcmp(args[cur_arg], "header")) {
5081 /* suboption header - needs additional argument for it */
5082 if (*(args[cur_arg+1]) == 0) {
5083 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5084 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005087 }
5088 free(curproxy->fwdfor_hdr_name);
5089 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5090 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5091 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005092 } else if (!strcmp(args[cur_arg], "if-none")) {
5093 curproxy->options &= ~PR_O_FF_ALWAYS;
5094 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005095 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005096 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005097 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005098 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005101 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005102 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005103 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005104 else if (!strcmp(args[1], "originalto")) {
5105 int cur_arg;
5106
5107 /* insert x-original-to field, but not for the IP address listed as an except.
5108 * set default options (ie: bitfield, header name, etc)
5109 */
5110
5111 curproxy->options |= PR_O_ORGTO;
5112
5113 free(curproxy->orgto_hdr_name);
5114 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5115 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5116
Willy Tarreau87cf5142011-08-19 22:57:24 +02005117 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005118 cur_arg = 2;
5119 while (*(args[cur_arg])) {
5120 if (!strcmp(args[cur_arg], "except")) {
5121 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005122 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 +02005123 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5124 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005127 }
5128 /* flush useless bits */
5129 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5130 cur_arg += 2;
5131 } else if (!strcmp(args[cur_arg], "header")) {
5132 /* suboption header - needs additional argument for it */
5133 if (*(args[cur_arg+1]) == 0) {
5134 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5135 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005138 }
5139 free(curproxy->orgto_hdr_name);
5140 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5141 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5142 cur_arg += 2;
5143 } else {
5144 /* unknown suboption - catchall */
5145 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5146 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005149 }
5150 } /* end while loop */
5151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 else {
5153 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreau93893792009-07-23 13:19:11 +02005157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005159 else if (!strcmp(args[0], "default_backend")) {
5160 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005161 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005162
5163 if (*(args[1]) == 0) {
5164 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005167 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005168 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005169 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005170
5171 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5172 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005175 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005177
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005178 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5179 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 +01005180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 /* enable reconnections to dispatch */
5183 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005184
5185 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005188 else if (!strcmp(args[0], "http-reuse")) {
5189 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5190 err_code |= ERR_WARN;
5191
5192 if (strcmp(args[1], "never") == 0) {
5193 /* enable a graceful server shutdown on an HTTP 404 response */
5194 curproxy->options &= ~PR_O_REUSE_MASK;
5195 curproxy->options |= PR_O_REUSE_NEVR;
5196 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5197 goto out;
5198 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005199 else if (strcmp(args[1], "safe") == 0) {
5200 /* enable a graceful server shutdown on an HTTP 404 response */
5201 curproxy->options &= ~PR_O_REUSE_MASK;
5202 curproxy->options |= PR_O_REUSE_SAFE;
5203 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5204 goto out;
5205 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005206 else if (strcmp(args[1], "aggressive") == 0) {
5207 curproxy->options &= ~PR_O_REUSE_MASK;
5208 curproxy->options |= PR_O_REUSE_AGGR;
5209 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5210 goto out;
5211 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005212 else if (strcmp(args[1], "always") == 0) {
5213 /* enable a graceful server shutdown on an HTTP 404 response */
5214 curproxy->options &= ~PR_O_REUSE_MASK;
5215 curproxy->options |= PR_O_REUSE_ALWS;
5216 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5217 goto out;
5218 }
5219 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005220 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
5224 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005225 else if (!strcmp(args[0], "http-check")) {
5226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005228
5229 if (strcmp(args[1], "disable-on-404") == 0) {
5230 /* enable a graceful server shutdown on an HTTP 404 response */
5231 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005232 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5233 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005234 }
Willy Tarreauef781042010-01-27 11:53:01 +01005235 else if (strcmp(args[1], "send-state") == 0) {
5236 /* enable emission of the apparent state of a server in HTTP checks */
5237 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005238 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5239 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005240 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005241 else if (strcmp(args[1], "expect") == 0) {
5242 const char *ptr_arg;
5243 int cur_arg;
5244
5245 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5246 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
5250
5251 cur_arg = 2;
5252 /* consider exclamation marks, sole or at the beginning of a word */
5253 while (*(ptr_arg = args[cur_arg])) {
5254 while (*ptr_arg == '!') {
5255 curproxy->options2 ^= PR_O2_EXP_INV;
5256 ptr_arg++;
5257 }
5258 if (*ptr_arg)
5259 break;
5260 cur_arg++;
5261 }
5262 /* now ptr_arg points to the beginning of a word past any possible
5263 * exclamation mark, and cur_arg is the argument which holds this word.
5264 */
5265 if (strcmp(ptr_arg, "status") == 0) {
5266 if (!*(args[cur_arg + 1])) {
5267 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5268 file, linenum, args[0], args[1], ptr_arg);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005273 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005274 curproxy->expect_str = strdup(args[cur_arg + 1]);
5275 }
5276 else if (strcmp(ptr_arg, "string") == 0) {
5277 if (!*(args[cur_arg + 1])) {
5278 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5279 file, linenum, args[0], args[1], ptr_arg);
5280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
5283 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005284 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005285 curproxy->expect_str = strdup(args[cur_arg + 1]);
5286 }
5287 else if (strcmp(ptr_arg, "rstatus") == 0) {
5288 if (!*(args[cur_arg + 1])) {
5289 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5290 file, linenum, args[0], args[1], ptr_arg);
5291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
5293 }
5294 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005295 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005296 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005297 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005298 free(curproxy->expect_regex);
5299 curproxy->expect_regex = NULL;
5300 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005301 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005302 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5303 error = NULL;
5304 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5305 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5306 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5307 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
5310 }
5311 }
5312 else if (strcmp(ptr_arg, "rstring") == 0) {
5313 if (!*(args[cur_arg + 1])) {
5314 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5315 file, linenum, args[0], args[1], ptr_arg);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
5319 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005320 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005321 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005322 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005323 free(curproxy->expect_regex);
5324 curproxy->expect_regex = NULL;
5325 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005326 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005327 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5328 error = NULL;
5329 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5330 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5331 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5332 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 }
5337 else {
5338 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5339 file, linenum, args[0], args[1], ptr_arg);
5340 err_code |= ERR_ALERT | ERR_FATAL;
5341 goto out;
5342 }
5343 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005344 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005345 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 +02005346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005348 }
5349 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005350 else if (!strcmp(args[0], "tcp-check")) {
5351 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5352 err_code |= ERR_WARN;
5353
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005354 if (strcmp(args[1], "comment") == 0) {
5355 int cur_arg;
5356 struct tcpcheck_rule *tcpcheck;
5357
5358 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005359 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005360 tcpcheck->action = TCPCHK_ACT_COMMENT;
5361
5362 if (!*args[cur_arg + 1]) {
5363 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5364 file, linenum, args[cur_arg]);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368
5369 tcpcheck->comment = strdup(args[cur_arg + 1]);
5370
5371 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005372 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5373 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005374 }
5375 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005376 const char *ptr_arg;
5377 int cur_arg;
5378 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005379
5380 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005381 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5382 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5383 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5384 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5385 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005386
Willy Tarreau5581c272015-05-13 12:24:53 +02005387 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5388 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5389 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5390 file, linenum);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005393 }
5394
5395 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005396 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005397 tcpcheck->action = TCPCHK_ACT_CONNECT;
5398
5399 /* parsing each parameters to fill up the rule */
5400 while (*(ptr_arg = args[cur_arg])) {
5401 /* tcp port */
5402 if (strcmp(args[cur_arg], "port") == 0) {
5403 if ( (atol(args[cur_arg + 1]) > 65535) ||
5404 (atol(args[cur_arg + 1]) < 1) ){
5405 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5406 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
5409 }
5410 tcpcheck->port = atol(args[cur_arg + 1]);
5411 cur_arg += 2;
5412 }
5413 /* send proxy protocol */
5414 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5415 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5416 cur_arg++;
5417 }
5418#ifdef USE_OPENSSL
5419 else if (strcmp(args[cur_arg], "ssl") == 0) {
5420 curproxy->options |= PR_O_TCPCHK_SSL;
5421 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5422 cur_arg++;
5423 }
5424#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005425 /* comment for this tcpcheck line */
5426 else if (strcmp(args[cur_arg], "comment") == 0) {
5427 if (!*args[cur_arg + 1]) {
5428 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5429 file, linenum, args[cur_arg]);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
5433 tcpcheck->comment = strdup(args[cur_arg + 1]);
5434 cur_arg += 2;
5435 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005436 else {
5437#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005438 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 +01005439#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005440 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 +01005441#endif /* USE_OPENSSL */
5442 file, linenum, args[0], args[1], args[cur_arg]);
5443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
5446
5447 }
5448
5449 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5450 }
5451 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005452 if (! *(args[2]) ) {
5453 /* SEND string expected */
5454 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5455 file, linenum, args[0], args[1], args[2]);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 } else {
5459 struct tcpcheck_rule *tcpcheck;
5460
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005461 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005462
5463 tcpcheck->action = TCPCHK_ACT_SEND;
5464 tcpcheck->string_len = strlen(args[2]);
5465 tcpcheck->string = strdup(args[2]);
5466 tcpcheck->expect_regex = NULL;
5467
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005468 /* comment for this tcpcheck line */
5469 if (strcmp(args[3], "comment") == 0) {
5470 if (!*args[4]) {
5471 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5472 file, linenum, args[3]);
5473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
5475 }
5476 tcpcheck->comment = strdup(args[4]);
5477 }
5478
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005479 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5480 }
5481 }
5482 else if (strcmp(args[1], "send-binary") == 0) {
5483 if (! *(args[2]) ) {
5484 /* SEND binary string expected */
5485 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5486 file, linenum, args[0], args[1], args[2]);
5487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
5489 } else {
5490 struct tcpcheck_rule *tcpcheck;
5491 char *err = NULL;
5492
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005493 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005494
5495 tcpcheck->action = TCPCHK_ACT_SEND;
5496 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5497 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5498 file, linenum, args[0], args[1], args[2], err);
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
5501 }
5502 tcpcheck->expect_regex = NULL;
5503
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005504 /* comment for this tcpcheck line */
5505 if (strcmp(args[3], "comment") == 0) {
5506 if (!*args[4]) {
5507 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5508 file, linenum, args[3]);
5509 err_code |= ERR_ALERT | ERR_FATAL;
5510 goto out;
5511 }
5512 tcpcheck->comment = strdup(args[4]);
5513 }
5514
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005515 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5516 }
5517 }
5518 else if (strcmp(args[1], "expect") == 0) {
5519 const char *ptr_arg;
5520 int cur_arg;
5521 int inverse = 0;
5522
5523 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5524 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528
5529 cur_arg = 2;
5530 /* consider exclamation marks, sole or at the beginning of a word */
5531 while (*(ptr_arg = args[cur_arg])) {
5532 while (*ptr_arg == '!') {
5533 inverse = !inverse;
5534 ptr_arg++;
5535 }
5536 if (*ptr_arg)
5537 break;
5538 cur_arg++;
5539 }
5540 /* now ptr_arg points to the beginning of a word past any possible
5541 * exclamation mark, and cur_arg is the argument which holds this word.
5542 */
5543 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005544 struct tcpcheck_rule *tcpcheck;
5545 char *err = NULL;
5546
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005547 if (!*(args[cur_arg + 1])) {
5548 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5549 file, linenum, args[0], args[1], ptr_arg);
5550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
5552 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005553
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005554 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005555
5556 tcpcheck->action = TCPCHK_ACT_EXPECT;
5557 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5558 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5559 file, linenum, args[0], args[1], args[2], err);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563 tcpcheck->expect_regex = NULL;
5564 tcpcheck->inverse = inverse;
5565
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005566 /* tcpcheck comment */
5567 cur_arg += 2;
5568 if (strcmp(args[cur_arg], "comment") == 0) {
5569 if (!*args[cur_arg + 1]) {
5570 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5571 file, linenum, args[cur_arg + 1]);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
5575 tcpcheck->comment = strdup(args[cur_arg + 1]);
5576 }
5577
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005578 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5579 }
5580 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005581 struct tcpcheck_rule *tcpcheck;
5582
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005583 if (!*(args[cur_arg + 1])) {
5584 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5585 file, linenum, args[0], args[1], ptr_arg);
5586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
5588 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005589
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005590 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005591
5592 tcpcheck->action = TCPCHK_ACT_EXPECT;
5593 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5594 tcpcheck->string = strdup(args[cur_arg + 1]);
5595 tcpcheck->expect_regex = NULL;
5596 tcpcheck->inverse = inverse;
5597
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005598 /* tcpcheck comment */
5599 cur_arg += 2;
5600 if (strcmp(args[cur_arg], "comment") == 0) {
5601 if (!*args[cur_arg + 1]) {
5602 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5603 file, linenum, args[cur_arg + 1]);
5604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 }
5607 tcpcheck->comment = strdup(args[cur_arg + 1]);
5608 }
5609
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005610 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5611 }
5612 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005613 struct tcpcheck_rule *tcpcheck;
5614
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005615 if (!*(args[cur_arg + 1])) {
5616 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5617 file, linenum, args[0], args[1], ptr_arg);
5618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005621
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005622 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005623
5624 tcpcheck->action = TCPCHK_ACT_EXPECT;
5625 tcpcheck->string_len = 0;
5626 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005627 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5628 error = NULL;
5629 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5630 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5631 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5632 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
5635 }
5636 tcpcheck->inverse = inverse;
5637
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005638 /* tcpcheck comment */
5639 cur_arg += 2;
5640 if (strcmp(args[cur_arg], "comment") == 0) {
5641 if (!*args[cur_arg + 1]) {
5642 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5643 file, linenum, args[cur_arg + 1]);
5644 err_code |= ERR_ALERT | ERR_FATAL;
5645 goto out;
5646 }
5647 tcpcheck->comment = strdup(args[cur_arg + 1]);
5648 }
5649
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005650 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5651 }
5652 else {
5653 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5654 file, linenum, args[0], args[1], ptr_arg);
5655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
5657 }
5658 }
5659 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005660 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
5663 }
5664 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005665 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005666 if (curproxy == &defproxy) {
5667 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005670 }
5671
Willy Tarreaub80c2302007-11-30 20:51:32 +01005672 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005674
5675 if (strcmp(args[1], "fail") == 0) {
5676 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005677 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005678 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5679 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005682 }
5683
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005684 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5685 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5686 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005689 }
5690 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5691 }
5692 else {
5693 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005694 err_code |= ERR_ALERT | ERR_FATAL;
5695 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005696 }
5697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698#ifdef TPROXY
5699 else if (!strcmp(args[0], "transparent")) {
5700 /* enable transparent proxy connections */
5701 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005702 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704 }
5705#endif
5706 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005707 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005708 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005709
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 if (*(args[1]) == 0) {
5711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 }
5715 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005716 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005719 else if (!strcmp(args[0], "backlog")) { /* backlog */
5720 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005722
5723 if (*(args[1]) == 0) {
5724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005727 }
5728 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5730 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005731 }
Willy Tarreau86034312006-12-29 00:10:33 +01005732 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005734 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005735
Willy Tarreau86034312006-12-29 00:10:33 +01005736 if (*(args[1]) == 0) {
5737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005740 }
5741 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5743 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5746 if (*(args[1]) == 0) {
5747 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005751 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5752 if (err) {
5753 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5754 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005757 }
5758 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 }
5762 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005763 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005764 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005765 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005766
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 if (curproxy == &defproxy) {
5768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005772 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005773 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005774
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005775 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005776 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005777 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005778 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005779 goto out;
5780 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005781
5782 proto = protocol_by_family(sk->ss_family);
5783 if (!proto || !proto->connect) {
5784 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5785 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
5789
5790 if (port1 != port2) {
5791 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5792 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005796
5797 if (!port1) {
5798 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5799 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
5802 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005803
William Lallemanddf1425a2015-04-28 20:17:49 +02005804 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5805 goto out;
5806
Willy Tarreaud5191e72010-02-09 20:50:45 +01005807 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005808 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 }
5810 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005812 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005813
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005814 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5815 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005820 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005821 /**
5822 * The syntax for hash-type config element is
5823 * hash-type {map-based|consistent} [[<algo>] avalanche]
5824 *
5825 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5826 */
5827 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005828
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5830 err_code |= ERR_WARN;
5831
5832 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005833 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5834 }
5835 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005836 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5837 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005838 else if (strcmp(args[1], "avalanche") == 0) {
5839 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]);
5840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005842 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005843 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005844 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005845 err_code |= ERR_ALERT | ERR_FATAL;
5846 goto out;
5847 }
Bhaskar98634f02013-10-29 23:30:51 -04005848
5849 /* set the hash function to use */
5850 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005851 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005852 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005853
5854 /* if consistent with no argument, then avalanche modifier is also applied */
5855 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5856 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005857 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005858 /* set the hash function */
5859 if (!strcmp(args[2], "sdbm")) {
5860 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5861 }
5862 else if (!strcmp(args[2], "djb2")) {
5863 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005864 }
5865 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005866 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005867 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005868 else if (!strcmp(args[2], "crc32")) {
5869 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5870 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005871 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005872 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 -05005873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
5875 }
5876
5877 /* set the hash modifier */
5878 if (!strcmp(args[3], "avalanche")) {
5879 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5880 }
5881 else if (*args[3]) {
5882 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
5885 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005886 }
William Lallemanda73203e2012-03-12 12:48:57 +01005887 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005888 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5889 if (*(args[1]) == 0) {
5890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
5893 }
5894 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5895 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5896 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
5900 }
William Lallemanda73203e2012-03-12 12:48:57 +01005901 else if (strcmp(args[0], "unique-id-format") == 0) {
5902 if (!*(args[1])) {
5903 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
William Lallemand3203ff42012-11-11 17:30:56 +01005907 if (*(args[2])) {
5908 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5909 err_code |= ERR_ALERT | ERR_FATAL;
5910 goto out;
5911 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005912 free(curproxy->conf.uniqueid_format_string);
5913 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005914
Willy Tarreau62a61232013-04-12 18:13:46 +02005915 free(curproxy->conf.uif_file);
5916 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5917 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005918 }
William Lallemanda73203e2012-03-12 12:48:57 +01005919
5920 else if (strcmp(args[0], "unique-id-header") == 0) {
5921 if (!*(args[1])) {
5922 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5923 err_code |= ERR_ALERT | ERR_FATAL;
5924 goto out;
5925 }
5926 free(curproxy->header_unique_id);
5927 curproxy->header_unique_id = strdup(args[1]);
5928 }
5929
William Lallemand723b73a2012-02-08 16:37:49 +01005930 else if (strcmp(args[0], "log-format") == 0) {
5931 if (!*(args[1])) {
5932 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
William Lallemand3203ff42012-11-11 17:30:56 +01005936 if (*(args[2])) {
5937 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
5940 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005941
Willy Tarreau62a61232013-04-12 18:13:46 +02005942 if (curproxy->conf.logformat_string != default_http_log_format &&
5943 curproxy->conf.logformat_string != default_tcp_log_format &&
5944 curproxy->conf.logformat_string != clf_http_log_format)
5945 free(curproxy->conf.logformat_string);
5946 curproxy->conf.logformat_string = strdup(args[1]);
5947
5948 free(curproxy->conf.lfs_file);
5949 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5950 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005951
5952 /* get a chance to improve log-format error reporting by
5953 * reporting the correct line-number when possible.
5954 */
5955 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5956 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5957 file, linenum, curproxy->id);
5958 err_code |= ERR_WARN;
5959 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005961 else if (!strcmp(args[0], "log-format-sd")) {
5962 if (!*(args[1])) {
5963 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
5967 if (*(args[2])) {
5968 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
5972
5973 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5974 free(curproxy->conf.logformat_sd_string);
5975 curproxy->conf.logformat_sd_string = strdup(args[1]);
5976
5977 free(curproxy->conf.lfsd_file);
5978 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5979 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5980
5981 /* get a chance to improve log-format-sd error reporting by
5982 * reporting the correct line-number when possible.
5983 */
5984 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5985 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5986 file, linenum, curproxy->id);
5987 err_code |= ERR_WARN;
5988 }
5989 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005990 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5991 if (*(args[1]) == 0) {
5992 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005996 chunk_destroy(&curproxy->log_tag);
5997 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005998 }
William Lallemand0f99e342011-10-12 17:50:54 +02005999 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6000 /* delete previous herited or defined syslog servers */
6001 struct logsrv *back;
6002
6003 if (*(args[1]) != 0) {
6004 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6005 err_code |= ERR_ALERT | ERR_FATAL;
6006 goto out;
6007 }
6008
William Lallemand723b73a2012-02-08 16:37:49 +01006009 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6010 LIST_DEL(&tmplogsrv->list);
6011 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006012 }
6013 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006014 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006015 struct logsrv *logsrv;
6016
Willy Tarreaubaaee002006-06-26 02:48:02 +02006017 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006018 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006019 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006020 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006021 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006022 LIST_INIT(&node->list);
6023 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 }
6026 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006027 struct sockaddr_storage *sk;
6028 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006029 int arg = 0;
6030 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006031
Vincent Bernat02779b62016-04-03 13:48:43 +02006032 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033
Willy Tarreau18324f52014-06-27 18:10:07 +02006034 /* just after the address, a length may be specified */
6035 if (strcmp(args[arg+2], "len") == 0) {
6036 len = atoi(args[arg+3]);
6037 if (len < 80 || len > 65535) {
6038 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6039 file, linenum, args[arg+3]);
6040 err_code |= ERR_ALERT | ERR_FATAL;
6041 goto out;
6042 }
6043 logsrv->maxlen = len;
6044
6045 /* skip these two args */
6046 arg += 2;
6047 }
6048 else
6049 logsrv->maxlen = MAX_SYSLOG_LEN;
6050
6051 if (logsrv->maxlen > global.max_syslog_len) {
6052 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006053 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6054 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6055 logline = my_realloc2(logline, global.max_syslog_len + 1);
6056 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006057 }
6058
Dragan Dosen1322d092015-09-22 16:05:32 +02006059 /* after the length, a format may be specified */
6060 if (strcmp(args[arg+2], "format") == 0) {
6061 logsrv->format = get_log_format(args[arg+3]);
6062 if (logsrv->format < 0) {
6063 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6064 err_code |= ERR_ALERT | ERR_FATAL;
6065 goto out;
6066 }
6067
6068 /* skip these two args */
6069 arg += 2;
6070 }
6071
William Lallemanddf1425a2015-04-28 20:17:49 +02006072 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6073 goto out;
6074
Willy Tarreau18324f52014-06-27 18:10:07 +02006075 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006076 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006077 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006078 err_code |= ERR_ALERT | ERR_FATAL;
6079 goto out;
6080
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081 }
6082
William Lallemand0f99e342011-10-12 17:50:54 +02006083 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006084 if (*(args[arg+3])) {
6085 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006086 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006087 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006088 err_code |= ERR_ALERT | ERR_FATAL;
6089 goto out;
6090
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
6092 }
6093
William Lallemand0f99e342011-10-12 17:50:54 +02006094 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006095 if (*(args[arg+4])) {
6096 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006097 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006098 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006099 err_code |= ERR_ALERT | ERR_FATAL;
6100 goto out;
6101
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006102 }
6103 }
6104
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006105 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006106 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006107 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006108 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006109 goto out;
6110 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006111
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006112 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006113
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006114 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006115 if (port1 != port2) {
6116 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6117 file, linenum, args[0], args[1]);
6118 err_code |= ERR_ALERT | ERR_FATAL;
6119 goto out;
6120 }
6121
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006122 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006123 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124 }
William Lallemand0f99e342011-10-12 17:50:54 +02006125
6126 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127 }
6128 else {
6129 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6130 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006133 }
6134 }
6135 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006136 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006137 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006138 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006139 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006140
Willy Tarreau977b8e42006-12-29 14:19:17 +01006141 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006142 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006143
Willy Tarreaubaaee002006-06-26 02:48:02 +02006144 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006145 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6146 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006147 err_code |= ERR_ALERT | ERR_FATAL;
6148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006150
6151 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006152 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6153 free(curproxy->conn_src.iface_name);
6154 curproxy->conn_src.iface_name = NULL;
6155 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006156
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006157 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006158 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006159 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006160 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006161 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006162 goto out;
6163 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006164
6165 proto = protocol_by_family(sk->ss_family);
6166 if (!proto || !proto->connect) {
6167 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006168 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006169 err_code |= ERR_ALERT | ERR_FATAL;
6170 goto out;
6171 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006172
6173 if (port1 != port2) {
6174 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6175 file, linenum, args[0], args[1]);
6176 err_code |= ERR_ALERT | ERR_FATAL;
6177 goto out;
6178 }
6179
Willy Tarreauef9a3602012-12-08 22:29:20 +01006180 curproxy->conn_src.source_addr = *sk;
6181 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006182
6183 cur_arg = 2;
6184 while (*(args[cur_arg])) {
6185 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006186#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006187 if (!*args[cur_arg + 1]) {
6188 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6189 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006190 err_code |= ERR_ALERT | ERR_FATAL;
6191 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006192 }
6193
6194 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006195 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6196 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006197 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006198 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6199 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006200 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6201 char *name, *end;
6202
6203 name = args[cur_arg+1] + 7;
6204 while (isspace(*name))
6205 name++;
6206
6207 end = name;
6208 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6209 end++;
6210
Willy Tarreauef9a3602012-12-08 22:29:20 +01006211 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6212 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6213 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6214 curproxy->conn_src.bind_hdr_len = end - name;
6215 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6216 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6217 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006218
6219 /* now look for an occurrence number */
6220 while (isspace(*end))
6221 end++;
6222 if (*end == ',') {
6223 end++;
6224 name = end;
6225 if (*end == '-')
6226 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006227 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006228 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006229 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006230 }
6231
Willy Tarreauef9a3602012-12-08 22:29:20 +01006232 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006233 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6234 " occurrences values smaller than %d.\n",
6235 file, linenum, MAX_HDR_HISTORY);
6236 err_code |= ERR_ALERT | ERR_FATAL;
6237 goto out;
6238 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006239 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006240 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006241
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006242 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006243 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006244 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006245 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006246 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006247 goto out;
6248 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006249
6250 proto = protocol_by_family(sk->ss_family);
6251 if (!proto || !proto->connect) {
6252 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6253 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006254 err_code |= ERR_ALERT | ERR_FATAL;
6255 goto out;
6256 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006257
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006258 if (port1 != port2) {
6259 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6260 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006261 err_code |= ERR_ALERT | ERR_FATAL;
6262 goto out;
6263 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006264 curproxy->conn_src.tproxy_addr = *sk;
6265 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006266 }
6267 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006268#else /* no TPROXY support */
6269 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006270 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006273#endif
6274 cur_arg += 2;
6275 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006276 }
6277
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006278 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6279#ifdef SO_BINDTODEVICE
6280 if (!*args[cur_arg + 1]) {
6281 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6282 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006283 err_code |= ERR_ALERT | ERR_FATAL;
6284 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006285 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006286 free(curproxy->conn_src.iface_name);
6287 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6288 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006289 global.last_checks |= LSTCHK_NETADM;
6290#else
6291 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6292 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006295#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006296 cur_arg += 2;
6297 continue;
6298 }
6299 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006300 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006301 err_code |= ERR_ALERT | ERR_FATAL;
6302 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006304 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006305 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6306 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6307 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006312 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6314 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006315 err_code |= ERR_ALERT | ERR_FATAL;
6316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006317 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318
6319 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006320 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006321 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006322 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 }
6325 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006326 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006327 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006328 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006329 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006331 }
6332 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006333 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006334 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006335 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006336 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338 }
6339 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006340 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006341 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006342 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006343 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 }
6346 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006347 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006348 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006349 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006353 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006354 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006355 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006356 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006358 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6363 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006364 err_code |= ERR_ALERT | ERR_FATAL;
6365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367
6368 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006369 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006370 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 }
6374 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006376 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006377 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
6381 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006383 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006384 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 }
6388 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006390 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006391 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006392 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 }
6395 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006396 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006397 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006398 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006402 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006403 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006404 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006405 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006407 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006410 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006411
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 if (curproxy == &defproxy) {
6413 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006414 err_code |= ERR_ALERT | ERR_FATAL;
6415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006417 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006418 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 if (*(args[1]) == 0) {
6421 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006422 err_code |= ERR_ALERT | ERR_FATAL;
6423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006424 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006425
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006426 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006427 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6428 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6429 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006430 err_code |= ERR_ALERT | ERR_FATAL;
6431 goto out;
6432 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006433 err_code |= warnif_cond_conflicts(cond,
6434 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6435 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006436 }
6437 else if (*args[2]) {
6438 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6439 file, linenum, args[0], args[2]);
6440 err_code |= ERR_ALERT | ERR_FATAL;
6441 goto out;
6442 }
6443
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006444 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006445 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006446 wl->s = strdup(args[1]);
6447 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006448 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 }
6450 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006451 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6453 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006454 err_code |= ERR_ALERT | ERR_FATAL;
6455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006457
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006459 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006460 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006461 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006463 }
6464 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006466 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006467 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006468 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 }
6471 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006472 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006473 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006474 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
6478 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6481 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006482 err_code |= ERR_ALERT | ERR_FATAL;
6483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
6485
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006487 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006488 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 }
6492 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006494 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006495 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 }
6499 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006501 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006502 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 }
6506 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006507 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006508
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 if (curproxy == &defproxy) {
6510 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006511 err_code |= ERR_ALERT | ERR_FATAL;
6512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006514 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006515 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517 if (*(args[1]) == 0) {
6518 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006519 err_code |= ERR_ALERT | ERR_FATAL;
6520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006521 }
6522
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006523 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006524 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6525 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6526 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006527 err_code |= ERR_ALERT | ERR_FATAL;
6528 goto out;
6529 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006530 err_code |= warnif_cond_conflicts(cond,
6531 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6532 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006533 }
6534 else if (*args[2]) {
6535 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6536 file, linenum, args[0], args[2]);
6537 err_code |= ERR_ALERT | ERR_FATAL;
6538 goto out;
6539 }
6540
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006541 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006542 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006543 wl->s = strdup(args[1]);
6544 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 }
6546 else if (!strcmp(args[0], "errorloc") ||
6547 !strcmp(args[0], "errorloc302") ||
6548 !strcmp(args[0], "errorloc303")) { /* error location */
6549 int errnum, errlen;
6550 char *err;
6551
Willy Tarreau977b8e42006-12-29 14:19:17 +01006552 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006553 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006554
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006556 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006557 err_code |= ERR_ALERT | ERR_FATAL;
6558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559 }
6560
6561 errnum = atol(args[1]);
6562 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006563 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6564 err = malloc(errlen);
6565 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006566 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006567 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6568 err = malloc(errlen);
6569 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 }
6571
Willy Tarreau0f772532006-12-23 20:51:41 +01006572 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6573 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006574 chunk_destroy(&curproxy->errmsg[rc]);
6575 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006576 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006579
6580 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006581 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6582 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 free(err);
6584 }
6585 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006586 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6587 int errnum, errlen, fd;
6588 char *err;
6589 struct stat stat;
6590
6591 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006592 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006593
6594 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006595 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006596 err_code |= ERR_ALERT | ERR_FATAL;
6597 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006598 }
6599
6600 fd = open(args[2], O_RDONLY);
6601 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6602 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6603 file, linenum, args[2], args[1]);
6604 if (fd >= 0)
6605 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006606 err_code |= ERR_ALERT | ERR_FATAL;
6607 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006608 }
6609
Willy Tarreau27a674e2009-08-17 07:23:33 +02006610 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006611 errlen = stat.st_size;
6612 } else {
6613 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006614 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006615 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006616 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006617 }
6618
6619 err = malloc(errlen); /* malloc() must succeed during parsing */
6620 errnum = read(fd, err, errlen);
6621 if (errnum != errlen) {
6622 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6623 file, linenum, args[2], args[1]);
6624 close(fd);
6625 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006626 err_code |= ERR_ALERT | ERR_FATAL;
6627 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006628 }
6629 close(fd);
6630
6631 errnum = atol(args[1]);
6632 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6633 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006634 chunk_destroy(&curproxy->errmsg[rc]);
6635 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006636 break;
6637 }
6638 }
6639
6640 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006641 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6642 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006643 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006644 free(err);
6645 }
6646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006647 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006648 struct cfg_kw_list *kwl;
6649 int index;
6650
6651 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6652 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6653 if (kwl->kw[index].section != CFG_LISTEN)
6654 continue;
6655 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6656 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006657 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006658 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006659 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006660 err_code |= ERR_ALERT | ERR_FATAL;
6661 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006662 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006663 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006664 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006665 err_code |= ERR_WARN;
6666 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006667 }
Willy Tarreau93893792009-07-23 13:19:11 +02006668 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006669 }
6670 }
6671 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006672
Willy Tarreau6daf3432008-01-22 16:44:08 +01006673 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006674 err_code |= ERR_ALERT | ERR_FATAL;
6675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006676 }
Willy Tarreau93893792009-07-23 13:19:11 +02006677 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006678 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006679 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006680}
6681
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006682int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006683cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6684{
6685#ifdef CONFIG_HAP_NS
6686 const char *err;
6687 const char *item = args[0];
6688
6689 if (!strcmp(item, "namespace_list")) {
6690 return 0;
6691 }
6692 else if (!strcmp(item, "namespace")) {
6693 size_t idx = 1;
6694 const char *current;
6695 while (*(current = args[idx++])) {
6696 err = invalid_char(current);
6697 if (err) {
6698 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6699 file, linenum, *err, item, current);
6700 return ERR_ALERT | ERR_FATAL;
6701 }
6702
6703 if (netns_store_lookup(current, strlen(current))) {
6704 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6705 file, linenum, current);
6706 return ERR_ALERT | ERR_FATAL;
6707 }
6708 if (!netns_store_insert(current)) {
6709 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6710 file, linenum, current);
6711 return ERR_ALERT | ERR_FATAL;
6712 }
6713 }
6714 }
6715
6716 return 0;
6717#else
6718 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6719 file, linenum);
6720 return ERR_ALERT | ERR_FATAL;
6721#endif
6722}
6723
6724int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006725cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6726{
6727
6728 int err_code = 0;
6729 const char *err;
6730
6731 if (!strcmp(args[0], "userlist")) { /* new userlist */
6732 struct userlist *newul;
6733
6734 if (!*args[1]) {
6735 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6736 file, linenum, args[0]);
6737 err_code |= ERR_ALERT | ERR_FATAL;
6738 goto out;
6739 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006740 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6741 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742
6743 err = invalid_char(args[1]);
6744 if (err) {
6745 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6746 file, linenum, *err, args[0], args[1]);
6747 err_code |= ERR_ALERT | ERR_FATAL;
6748 goto out;
6749 }
6750
6751 for (newul = userlist; newul; newul = newul->next)
6752 if (!strcmp(newul->name, args[1])) {
6753 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6754 file, linenum, args[1]);
6755 err_code |= ERR_WARN;
6756 goto out;
6757 }
6758
Vincent Bernat02779b62016-04-03 13:48:43 +02006759 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006760 if (!newul) {
6761 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6762 err_code |= ERR_ALERT | ERR_ABORT;
6763 goto out;
6764 }
6765
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006767 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006768 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6769 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006770 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006771 goto out;
6772 }
6773
6774 newul->next = userlist;
6775 userlist = newul;
6776
6777 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006778 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006779 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006780 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006781
6782 if (!*args[1]) {
6783 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6784 file, linenum, args[0]);
6785 err_code |= ERR_ALERT | ERR_FATAL;
6786 goto out;
6787 }
6788
6789 err = invalid_char(args[1]);
6790 if (err) {
6791 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6792 file, linenum, *err, args[0], args[1]);
6793 err_code |= ERR_ALERT | ERR_FATAL;
6794 goto out;
6795 }
6796
William Lallemand4ac9f542015-05-28 18:03:51 +02006797 if (!userlist)
6798 goto out;
6799
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006800 for (ag = userlist->groups; ag; ag = ag->next)
6801 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6803 file, linenum, args[1], userlist->name);
6804 err_code |= ERR_ALERT;
6805 goto out;
6806 }
6807
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006808 ag = calloc(1, sizeof(*ag));
6809 if (!ag) {
6810 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6811 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006812 goto out;
6813 }
6814
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006815 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006816 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006817 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6818 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006819 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006820 goto out;
6821 }
6822
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006823 cur_arg = 2;
6824
6825 while (*args[cur_arg]) {
6826 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006827 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006828 cur_arg += 2;
6829 continue;
6830 } else {
6831 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6832 file, linenum, args[0]);
6833 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006834 free(ag->groupusers);
6835 free(ag->name);
6836 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006837 goto out;
6838 }
6839 }
6840
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006841 ag->next = userlist->groups;
6842 userlist->groups = ag;
6843
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006844 } else if (!strcmp(args[0], "user")) { /* new user */
6845 struct auth_users *newuser;
6846 int cur_arg;
6847
6848 if (!*args[1]) {
6849 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6850 file, linenum, args[0]);
6851 err_code |= ERR_ALERT | ERR_FATAL;
6852 goto out;
6853 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006854 if (!userlist)
6855 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006856
6857 for (newuser = userlist->users; newuser; newuser = newuser->next)
6858 if (!strcmp(newuser->user, args[1])) {
6859 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6860 file, linenum, args[1], userlist->name);
6861 err_code |= ERR_ALERT;
6862 goto out;
6863 }
6864
Vincent Bernat02779b62016-04-03 13:48:43 +02006865 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006866 if (!newuser) {
6867 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6868 err_code |= ERR_ALERT | ERR_ABORT;
6869 goto out;
6870 }
6871
6872 newuser->user = strdup(args[1]);
6873
6874 newuser->next = userlist->users;
6875 userlist->users = newuser;
6876
6877 cur_arg = 2;
6878
6879 while (*args[cur_arg]) {
6880 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006881#ifdef CONFIG_HAP_CRYPT
6882 if (!crypt("", args[cur_arg + 1])) {
6883 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6884 file, linenum, newuser->user);
6885 err_code |= ERR_ALERT | ERR_FATAL;
6886 goto out;
6887 }
6888#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006889 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6890 file, linenum);
6891 err_code |= ERR_ALERT;
6892#endif
6893 newuser->pass = strdup(args[cur_arg + 1]);
6894 cur_arg += 2;
6895 continue;
6896 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6897 newuser->pass = strdup(args[cur_arg + 1]);
6898 newuser->flags |= AU_O_INSECURE;
6899 cur_arg += 2;
6900 continue;
6901 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006902 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006903 cur_arg += 2;
6904 continue;
6905 } else {
6906 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6907 file, linenum, args[0]);
6908 err_code |= ERR_ALERT | ERR_FATAL;
6909 goto out;
6910 }
6911 }
6912 } else {
6913 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6914 err_code |= ERR_ALERT | ERR_FATAL;
6915 }
6916
6917out:
6918 return err_code;
6919}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006920
Christopher Faulet79bdef32016-11-04 22:36:15 +01006921int
6922cfg_parse_scope(const char *file, int linenum, char *line)
6923{
6924 char *beg, *end, *scope = NULL;
6925 int err_code = 0;
6926 const char *err;
6927
6928 beg = line + 1;
6929 end = strchr(beg, ']');
6930
6931 /* Detect end of scope declaration */
6932 if (!end || end == beg) {
6933 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6934 file, linenum);
6935 err_code |= ERR_ALERT | ERR_FATAL;
6936 goto out;
6937 }
6938
6939 /* Get scope name and check its validity */
6940 scope = my_strndup(beg, end-beg);
6941 err = invalid_char(scope);
6942 if (err) {
6943 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6944 file, linenum, *err);
6945 err_code |= ERR_ALERT | ERR_ABORT;
6946 goto out;
6947 }
6948
6949 /* Be sure to have a scope declaration alone on its line */
6950 line = end+1;
6951 while (isspace((unsigned char)*line))
6952 line++;
6953 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6954 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6955 file, linenum, *line);
6956 err_code |= ERR_ALERT | ERR_ABORT;
6957 goto out;
6958 }
6959
6960 /* We have a valid scope declaration, save it */
6961 free(cfg_scope);
6962 cfg_scope = scope;
6963 scope = NULL;
6964
6965 out:
6966 free(scope);
6967 return err_code;
6968}
6969
Willy Tarreaubaaee002006-06-26 02:48:02 +02006970/*
6971 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006972 * Returns the error code, 0 if OK, or any combination of :
6973 * - ERR_ABORT: must abort ASAP
6974 * - ERR_FATAL: we can continue parsing but not start the service
6975 * - ERR_WARN: a warning has been emitted
6976 * - ERR_ALERT: an alert has been emitted
6977 * Only the two first ones can stop processing, the two others are just
6978 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006980int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006981{
William Lallemand64e84512015-05-12 14:25:37 +02006982 char *thisline;
6983 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006984 FILE *f;
6985 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006986 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006987 struct cfg_section *cs = NULL;
6988 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006989 int readbytes = 0;
6990
6991 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006992 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006993 return -1;
6994 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006995
David Carlier97880bb2016-04-08 10:35:26 +01006996 if ((f=fopen(file,"r")) == NULL) {
6997 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006998 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007000
William Lallemandb2f07452015-05-12 14:27:13 +02007001next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007002 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007003 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007004 char *end;
7005 char *args[MAX_LINE_ARGS + 1];
7006 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007007 int dquote = 0; /* double quote */
7008 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007009
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010 linenum++;
7011
7012 end = line + strlen(line);
7013
William Lallemand64e84512015-05-12 14:25:37 +02007014 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007015 /* Check if we reached the limit and the last char is not \n.
7016 * Watch out for the last line without the terminating '\n'!
7017 */
William Lallemand64e84512015-05-12 14:25:37 +02007018 char *newline;
7019 int newlinesize = linesize * 2;
7020
7021 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7022 if (newline == NULL) {
7023 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7024 file, linenum);
7025 err_code |= ERR_ALERT | ERR_FATAL;
7026 continue;
7027 }
7028
7029 readbytes = linesize - 1;
7030 linesize = newlinesize;
7031 thisline = newline;
7032 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007033 }
7034
William Lallemand64e84512015-05-12 14:25:37 +02007035 readbytes = 0;
7036
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007038 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007040
Christopher Faulet79bdef32016-11-04 22:36:15 +01007041
7042 if (*line == '[') {/* This is the begining if a scope */
7043 err_code |= cfg_parse_scope(file, linenum, line);
7044 goto next_line;
7045 }
7046
Willy Tarreaubaaee002006-06-26 02:48:02 +02007047 arg = 0;
7048 args[arg] = line;
7049
7050 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007051 if (*line == '"' && !squote) { /* double quote outside single quotes */
7052 if (dquote)
7053 dquote = 0;
7054 else
7055 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007056 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007057 end--;
7058 }
7059 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7060 if (squote)
7061 squote = 0;
7062 else
7063 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007064 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007065 end--;
7066 }
7067 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007068 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7069 * C equivalent value. Other combinations left unchanged (eg: \1).
7070 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071 int skip = 0;
7072 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7073 *line = line[1];
7074 skip = 1;
7075 }
7076 else if (line[1] == 'r') {
7077 *line = '\r';
7078 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 else if (line[1] == 'n') {
7081 *line = '\n';
7082 skip = 1;
7083 }
7084 else if (line[1] == 't') {
7085 *line = '\t';
7086 skip = 1;
7087 }
7088 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007089 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007090 unsigned char hex1, hex2;
7091 hex1 = toupper(line[2]) - '0';
7092 hex2 = toupper(line[3]) - '0';
7093 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7094 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7095 *line = (hex1<<4) + hex2;
7096 skip = 3;
7097 }
7098 else {
7099 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007100 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007102 } else if (line[1] == '"') {
7103 *line = '"';
7104 skip = 1;
7105 } else if (line[1] == '\'') {
7106 *line = '\'';
7107 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007108 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7109 *line = '$';
7110 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007111 }
7112 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007113 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 end -= skip;
7115 }
7116 line++;
7117 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007118 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007119 /* end of string, end of loop */
7120 *line = 0;
7121 break;
7122 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007123 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007124 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007125 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007126 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007127 line++;
7128 args[++arg] = line;
7129 }
William Lallemandb2f07452015-05-12 14:27:13 +02007130 else if (dquote && *line == '$') {
7131 /* environment variables are evaluated inside double quotes */
7132 char *var_beg;
7133 char *var_end;
7134 char save_char;
7135 char *value;
7136 int val_len;
7137 int newlinesize;
7138 int braces = 0;
7139
7140 var_beg = line + 1;
7141 var_end = var_beg;
7142
7143 if (*var_beg == '{') {
7144 var_beg++;
7145 var_end++;
7146 braces = 1;
7147 }
7148
7149 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7150 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7151 err_code |= ERR_ALERT | ERR_FATAL;
7152 goto next_line; /* skip current line */
7153 }
7154
7155 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7156 var_end++;
7157
7158 save_char = *var_end;
7159 *var_end = '\0';
7160 value = getenv(var_beg);
7161 *var_end = save_char;
7162 val_len = value ? strlen(value) : 0;
7163
7164 if (braces) {
7165 if (*var_end == '}') {
7166 var_end++;
7167 braces = 0;
7168 } else {
7169 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7170 err_code |= ERR_ALERT | ERR_FATAL;
7171 goto next_line; /* skip current line */
7172 }
7173 }
7174
7175 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7176
7177 /* if not enough space in thisline */
7178 if (newlinesize > linesize) {
7179 char *newline;
7180
7181 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7182 if (newline == NULL) {
7183 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7184 err_code |= ERR_ALERT | ERR_FATAL;
7185 goto next_line; /* slip current line */
7186 }
7187 /* recompute pointers if realloc returns a new pointer */
7188 if (newline != thisline) {
7189 int i;
7190 int diff;
7191
7192 for (i = 0; i <= arg; i++) {
7193 diff = args[i] - thisline;
7194 args[i] = newline + diff;
7195 }
7196
7197 diff = var_end - thisline;
7198 var_end = newline + diff;
7199 diff = end - thisline;
7200 end = newline + diff;
7201 diff = line - thisline;
7202 line = newline + diff;
7203 thisline = newline;
7204 }
7205 linesize = newlinesize;
7206 }
7207
7208 /* insert value inside the line */
7209 memmove(line + val_len, var_end, end - var_end + 1);
7210 memcpy(line, value, val_len);
7211 end += val_len - (var_end - line);
7212 line += val_len;
7213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007214 else {
7215 line++;
7216 }
7217 }
William Lallemandb2f07452015-05-12 14:27:13 +02007218
William Lallemandf9873ba2015-05-05 17:37:14 +02007219 if (dquote) {
7220 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7221 err_code |= ERR_ALERT | ERR_FATAL;
7222 }
7223
7224 if (squote) {
7225 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7226 err_code |= ERR_ALERT | ERR_FATAL;
7227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007228
7229 /* empty line */
7230 if (!**args)
7231 continue;
7232
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007233 if (*line) {
7234 /* we had to stop due to too many args.
7235 * Let's terminate the string, print the offending part then cut the
7236 * last arg.
7237 */
7238 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7239 line++;
7240 *line = '\0';
7241
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007242 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007243 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007244 err_code |= ERR_ALERT | ERR_FATAL;
7245 args[arg] = line;
7246 }
7247
Willy Tarreau540abe42007-05-02 20:50:16 +02007248 /* zero out remaining args and ensure that at least one entry
7249 * is zeroed out.
7250 */
7251 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007252 args[arg] = line;
7253 }
7254
Willy Tarreau3842f002009-06-14 11:39:52 +02007255 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007256 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007257 char *tmp;
7258
Willy Tarreau3842f002009-06-14 11:39:52 +02007259 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007260 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007261 for (arg=0; *args[arg+1]; arg++)
7262 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007263 *tmp = '\0'; // fix the next arg to \0
7264 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007265 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007266 else if (!strcmp(args[0], "default")) {
7267 kwm = KWM_DEF;
7268 for (arg=0; *args[arg+1]; arg++)
7269 args[arg] = args[arg+1]; // shift args after inversion
7270 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007271
William Lallemand0f99e342011-10-12 17:50:54 +02007272 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7273 strcmp(args[0], "log") != 0) {
7274 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007275 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007276 }
7277
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007278 /* detect section start */
7279 list_for_each_entry(ics, &sections, list) {
7280 if (strcmp(args[0], ics->section_name) == 0) {
7281 cursection = ics->section_name;
7282 cs = ics;
7283 break;
7284 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007285 }
7286
Willy Tarreaubaaee002006-06-26 02:48:02 +02007287 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007288 if (cs)
7289 err_code |= cs->section_parser(file, linenum, args, kwm);
7290 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007291 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007292 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007293 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007294
7295 if (err_code & ERR_ABORT)
7296 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007297 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007298 free(cfg_scope);
7299 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007300 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007301 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007302 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007303 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007304}
7305
Willy Tarreau64ab6072014-09-16 12:17:36 +02007306/* This function propagates processes from frontend <from> to backend <to> so
7307 * that it is always guaranteed that a backend pointed to by a frontend is
7308 * bound to all of its processes. After that, if the target is a "listen"
7309 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007310 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007311 * checked first to ensure that <to> is already bound to all processes of
7312 * <from>, there is no risk of looping and we ensure to follow the shortest
7313 * path to the destination.
7314 *
7315 * It is possible to set <to> to NULL for the first call so that the function
7316 * takes care of visiting the initial frontend in <from>.
7317 *
7318 * It is important to note that the function relies on the fact that all names
7319 * have already been resolved.
7320 */
7321void propagate_processes(struct proxy *from, struct proxy *to)
7322{
7323 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324
7325 if (to) {
7326 /* check whether we need to go down */
7327 if (from->bind_proc &&
7328 (from->bind_proc & to->bind_proc) == from->bind_proc)
7329 return;
7330
7331 if (!from->bind_proc && !to->bind_proc)
7332 return;
7333
7334 to->bind_proc = from->bind_proc ?
7335 (to->bind_proc | from->bind_proc) : 0;
7336
7337 /* now propagate down */
7338 from = to;
7339 }
7340
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007341 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007342 return;
7343
Willy Tarreauf6b70012014-12-18 14:00:43 +01007344 if (from->state == PR_STSTOPPED)
7345 return;
7346
Willy Tarreau64ab6072014-09-16 12:17:36 +02007347 /* default_backend */
7348 if (from->defbe.be)
7349 propagate_processes(from, from->defbe.be);
7350
7351 /* use_backend */
7352 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007353 if (rule->dynamic)
7354 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007355 to = rule->be.backend;
7356 propagate_processes(from, to);
7357 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007358}
7359
Willy Tarreaubb925012009-07-23 13:36:36 +02007360/*
7361 * Returns the error code, 0 if OK, or any combination of :
7362 * - ERR_ABORT: must abort ASAP
7363 * - ERR_FATAL: we can continue parsing but not start the service
7364 * - ERR_WARN: a warning has been emitted
7365 * - ERR_ALERT: an alert has been emitted
7366 * Only the two first ones can stop processing, the two others are just
7367 * indicators.
7368 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007369int check_config_validity()
7370{
7371 int cfgerr = 0;
7372 struct proxy *curproxy = NULL;
7373 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007374 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007375 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007376 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007377 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007378
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007379 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007380 /*
7381 * Now, check for the integrity of all that we have collected.
7382 */
7383
7384 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007385 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007386
Willy Tarreau193b8c62012-11-22 00:17:38 +01007387 if (!global.tune.max_http_hdr)
7388 global.tune.max_http_hdr = MAX_HTTP_HDR;
7389
7390 if (!global.tune.cookie_len)
7391 global.tune.cookie_len = CAPTURE_LEN;
7392
7393 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7394
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007395 /* Post initialisation of the users and groups lists. */
7396 err_code = userlist_postinit();
7397 if (err_code != ERR_NONE)
7398 goto out;
7399
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007400 /* first, we will invert the proxy list order */
7401 curproxy = NULL;
7402 while (proxy) {
7403 struct proxy *next;
7404
7405 next = proxy->next;
7406 proxy->next = curproxy;
7407 curproxy = proxy;
7408 if (!next)
7409 break;
7410 proxy = next;
7411 }
7412
Willy Tarreau419ead82014-09-16 13:41:21 +02007413 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007414 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007415 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007416 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007417 struct act_rule *trule;
7418 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007419 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007420 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007421 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007422
Willy Tarreau050536d2012-10-04 08:47:34 +02007423 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007424 /* proxy ID not set, use automatic numbering with first
7425 * spare entry starting with next_pxid.
7426 */
7427 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7428 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7429 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007430 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007431 next_pxid++;
7432
Willy Tarreau55ea7572007-06-17 19:56:27 +02007433
Willy Tarreaubaaee002006-06-26 02:48:02 +02007434 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007435 /* ensure we don't keep listeners uselessly bound */
7436 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007437 free((void *)curproxy->table.peers.name);
7438 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007439 continue;
7440 }
7441
Willy Tarreau102df612014-05-07 23:56:38 +02007442 /* Check multi-process mode compatibility for the current proxy */
7443
7444 if (curproxy->bind_proc) {
7445 /* an explicit bind-process was specified, let's check how many
7446 * processes remain.
7447 */
David Carliere6c39412015-07-02 07:00:17 +00007448 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007449
7450 curproxy->bind_proc &= nbits(global.nbproc);
7451 if (!curproxy->bind_proc && nbproc == 1) {
7452 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);
7453 curproxy->bind_proc = 1;
7454 }
7455 else if (!curproxy->bind_proc && nbproc > 1) {
7456 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);
7457 curproxy->bind_proc = 0;
7458 }
7459 }
7460
Willy Tarreau3d209582014-05-09 17:06:11 +02007461 /* check and reduce the bind-proc of each listener */
7462 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7463 unsigned long mask;
7464
7465 if (!bind_conf->bind_proc)
7466 continue;
7467
7468 mask = nbits(global.nbproc);
7469 if (curproxy->bind_proc)
7470 mask &= curproxy->bind_proc;
7471 /* mask cannot be null here thanks to the previous checks */
7472
David Carliere6c39412015-07-02 07:00:17 +00007473 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007474 bind_conf->bind_proc &= mask;
7475
7476 if (!bind_conf->bind_proc && nbproc == 1) {
7477 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",
7478 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7479 bind_conf->bind_proc = mask & ~(mask - 1);
7480 }
7481 else if (!bind_conf->bind_proc && nbproc > 1) {
7482 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",
7483 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7484 bind_conf->bind_proc = 0;
7485 }
7486 }
7487
Willy Tarreauff01a212009-03-15 13:46:16 +01007488 switch (curproxy->mode) {
7489 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007490 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007491 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007492 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7493 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007494 cfgerr++;
7495 }
7496
7497 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007498 Warning("config : servers will be ignored for %s '%s'.\n",
7499 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007500 break;
7501
7502 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007503 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007504 break;
7505
7506 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007507 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007508 break;
7509 }
7510
Willy Tarreauf3934b82015-08-11 11:36:45 +02007511 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7512 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7513 proxy_type_str(curproxy), curproxy->id);
7514 err_code |= ERR_WARN;
7515 }
7516
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007517 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007518 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007519 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007520 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7521 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007522 cfgerr++;
7523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007524#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007525 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007526 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7527 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007528 cfgerr++;
7529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007530#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007531 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007532 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7533 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007534 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007535 }
7536 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007537 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007538 /* If no LB algo is set in a backend, and we're not in
7539 * transparent mode, dispatch mode nor proxy mode, we
7540 * want to use balance roundrobin by default.
7541 */
7542 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7543 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007544 }
7545 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007546
Willy Tarreau1620ec32011-08-06 17:05:02 +02007547 if (curproxy->options & PR_O_DISPATCH)
7548 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7549 else if (curproxy->options & PR_O_HTTP_PROXY)
7550 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7551 else if (curproxy->options & PR_O_TRANSP)
7552 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007553
Willy Tarreau1620ec32011-08-06 17:05:02 +02007554 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7555 if (curproxy->options & PR_O_DISABLE404) {
7556 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7557 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7558 err_code |= ERR_WARN;
7559 curproxy->options &= ~PR_O_DISABLE404;
7560 }
7561 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7562 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7563 "send-state", proxy_type_str(curproxy), curproxy->id);
7564 err_code |= ERR_WARN;
7565 curproxy->options &= ~PR_O2_CHK_SNDST;
7566 }
Willy Tarreauef781042010-01-27 11:53:01 +01007567 }
7568
Simon Horman98637e52014-06-20 12:30:16 +09007569 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7570 if (!global.external_check) {
7571 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7572 curproxy->id, "option external-check");
7573 cfgerr++;
7574 }
7575 if (!curproxy->check_command) {
7576 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7577 curproxy->id, "option external-check");
7578 cfgerr++;
7579 }
7580 }
7581
Simon Horman64e34162015-02-06 11:11:57 +09007582 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007583 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7584 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007585 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7586 "'email-alert myhostname', or 'email-alert to' "
7587 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007588 "to be present).\n",
7589 proxy_type_str(curproxy), curproxy->id);
7590 err_code |= ERR_WARN;
7591 free_email_alert(curproxy);
7592 }
7593 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007594 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007595 }
7596
Simon Horman98637e52014-06-20 12:30:16 +09007597 if (curproxy->check_command) {
7598 int clear = 0;
7599 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7600 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7601 "external-check command", proxy_type_str(curproxy), curproxy->id);
7602 err_code |= ERR_WARN;
7603 clear = 1;
7604 }
7605 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007606 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007607 curproxy->id, "external-check command");
7608 cfgerr++;
7609 }
7610 if (clear) {
7611 free(curproxy->check_command);
7612 curproxy->check_command = NULL;
7613 }
7614 }
7615
7616 if (curproxy->check_path) {
7617 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7618 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7619 "external-check path", proxy_type_str(curproxy), curproxy->id);
7620 err_code |= ERR_WARN;
7621 free(curproxy->check_path);
7622 curproxy->check_path = NULL;
7623 }
7624 }
7625
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007626 /* if a default backend was specified, let's find it */
7627 if (curproxy->defbe.name) {
7628 struct proxy *target;
7629
Willy Tarreauafb39922015-05-26 12:04:09 +02007630 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007631 if (!target) {
7632 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7633 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007634 cfgerr++;
7635 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007636 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7637 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007638 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007639 } else if (target->mode != curproxy->mode &&
7640 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7641
7642 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7643 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7644 curproxy->conf.file, curproxy->conf.line,
7645 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7646 target->conf.file, target->conf.line);
7647 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007648 } else {
7649 free(curproxy->defbe.name);
7650 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007651
7652 /* Emit a warning if this proxy also has some servers */
7653 if (curproxy->srv) {
7654 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7655 curproxy->id);
7656 err_code |= ERR_WARN;
7657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007658 }
7659 }
7660
Willy Tarreau55ea7572007-06-17 19:56:27 +02007661 /* find the target proxy for 'use_backend' rules */
7662 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007663 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007664 struct logformat_node *node;
7665 char *pxname;
7666
7667 /* Try to parse the string as a log format expression. If the result
7668 * of the parsing is only one entry containing a simple string, then
7669 * it's a standard string corresponding to a static rule, thus the
7670 * parsing is cancelled and be.name is restored to be resolved.
7671 */
7672 pxname = rule->be.name;
7673 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007674 curproxy->conf.args.ctx = ARGC_UBK;
7675 curproxy->conf.args.file = rule->file;
7676 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007677 err = NULL;
7678 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7679 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7680 rule->file, rule->line, pxname, err);
7681 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007682 cfgerr++;
7683 continue;
7684 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007685 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7686
7687 if (!LIST_ISEMPTY(&rule->be.expr)) {
7688 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7689 rule->dynamic = 1;
7690 free(pxname);
7691 continue;
7692 }
7693 /* simple string: free the expression and fall back to static rule */
7694 free(node->arg);
7695 free(node);
7696 }
7697
7698 rule->dynamic = 0;
7699 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007700
Willy Tarreauafb39922015-05-26 12:04:09 +02007701 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007702 if (!target) {
7703 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7704 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007705 cfgerr++;
7706 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007707 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7708 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007709 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007710 } else if (target->mode != curproxy->mode &&
7711 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7712
7713 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7714 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7715 curproxy->conf.file, curproxy->conf.line,
7716 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7717 target->conf.file, target->conf.line);
7718 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007719 } else {
7720 free((void *)rule->be.name);
7721 rule->be.backend = target;
7722 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007723 }
7724
Willy Tarreau64ab6072014-09-16 12:17:36 +02007725 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007726 list_for_each_entry(srule, &curproxy->server_rules, list) {
7727 struct server *target = findserver(curproxy, srule->srv.name);
7728
7729 if (!target) {
7730 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7731 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7732 cfgerr++;
7733 continue;
7734 }
7735 free((void *)srule->srv.name);
7736 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007737 }
7738
Emeric Brunb982a3d2010-01-04 15:45:53 +01007739 /* find the target table for 'stick' rules */
7740 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7741 struct proxy *target;
7742
Emeric Brun1d33b292010-01-04 15:47:17 +01007743 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7744 if (mrule->flags & STK_IS_STORE)
7745 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7746
Emeric Brunb982a3d2010-01-04 15:45:53 +01007747 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007748 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007749 else
7750 target = curproxy;
7751
7752 if (!target) {
7753 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7754 curproxy->id, mrule->table.name);
7755 cfgerr++;
7756 }
7757 else if (target->table.size == 0) {
7758 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7759 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7760 cfgerr++;
7761 }
Willy Tarreau12785782012-04-27 21:37:17 +02007762 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7763 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007764 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7765 cfgerr++;
7766 }
7767 else {
7768 free((void *)mrule->table.name);
7769 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007770 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007771 }
7772 }
7773
7774 /* find the target table for 'store response' rules */
7775 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7776 struct proxy *target;
7777
Emeric Brun1d33b292010-01-04 15:47:17 +01007778 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7779
Emeric Brunb982a3d2010-01-04 15:45:53 +01007780 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007781 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007782 else
7783 target = curproxy;
7784
7785 if (!target) {
7786 Alert("Proxy '%s': unable to find store table '%s'.\n",
7787 curproxy->id, mrule->table.name);
7788 cfgerr++;
7789 }
7790 else if (target->table.size == 0) {
7791 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7792 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7793 cfgerr++;
7794 }
Willy Tarreau12785782012-04-27 21:37:17 +02007795 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7796 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007797 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7798 cfgerr++;
7799 }
7800 else {
7801 free((void *)mrule->table.name);
7802 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007803 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007804 }
7805 }
7806
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007807 /* find the target table for 'tcp-request' layer 4 rules */
7808 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7809 struct proxy *target;
7810
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007811 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007812 continue;
7813
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007814 if (trule->arg.trk_ctr.table.n)
7815 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007816 else
7817 target = curproxy;
7818
7819 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007820 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007821 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007822 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007823 cfgerr++;
7824 }
7825 else if (target->table.size == 0) {
7826 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007827 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007828 cfgerr++;
7829 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007830 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007831 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007832 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007833 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007834 cfgerr++;
7835 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007836 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007837 free(trule->arg.trk_ctr.table.n);
7838 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007839 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007840 * to pass a list of counters to track and allocate them right here using
7841 * stktable_alloc_data_type().
7842 */
7843 }
7844 }
7845
Willy Tarreau620408f2016-10-21 16:37:51 +02007846 /* find the target table for 'tcp-request' layer 5 rules */
7847 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7848 struct proxy *target;
7849
7850 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7851 continue;
7852
7853 if (trule->arg.trk_ctr.table.n)
7854 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7855 else
7856 target = curproxy;
7857
7858 if (!target) {
7859 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7860 curproxy->id, trule->arg.trk_ctr.table.n,
7861 tcp_trk_idx(trule->action));
7862 cfgerr++;
7863 }
7864 else if (target->table.size == 0) {
7865 Alert("Proxy '%s': table '%s' used but not configured.\n",
7866 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7867 cfgerr++;
7868 }
7869 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7870 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7871 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7872 tcp_trk_idx(trule->action));
7873 cfgerr++;
7874 }
7875 else {
7876 free(trule->arg.trk_ctr.table.n);
7877 trule->arg.trk_ctr.table.t = &target->table;
7878 /* Note: if we decide to enhance the track-sc syntax, we may be able
7879 * to pass a list of counters to track and allocate them right here using
7880 * stktable_alloc_data_type().
7881 */
7882 }
7883 }
7884
Willy Tarreaud1f96522010-08-03 19:34:32 +02007885 /* find the target table for 'tcp-request' layer 6 rules */
7886 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7887 struct proxy *target;
7888
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007889 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007890 continue;
7891
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007892 if (trule->arg.trk_ctr.table.n)
7893 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007894 else
7895 target = curproxy;
7896
7897 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007898 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007899 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007900 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007901 cfgerr++;
7902 }
7903 else if (target->table.size == 0) {
7904 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007905 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007906 cfgerr++;
7907 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007908 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007909 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007910 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007911 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007912 cfgerr++;
7913 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007914 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007915 free(trule->arg.trk_ctr.table.n);
7916 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007917 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007918 * to pass a list of counters to track and allocate them right here using
7919 * stktable_alloc_data_type().
7920 */
7921 }
7922 }
7923
Baptiste Assmanne9544932015-11-03 23:31:35 +01007924 /* parse http-request capture rules to ensure id really exists */
7925 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7926 if (hrqrule->action != ACT_CUSTOM ||
7927 hrqrule->action_ptr != http_action_req_capture_by_id)
7928 continue;
7929
7930 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7931 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7932 curproxy->id, hrqrule->arg.capid.idx);
7933 cfgerr++;
7934 }
7935 }
7936
7937 /* parse http-response capture rules to ensure id really exists */
7938 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7939 if (hrqrule->action != ACT_CUSTOM ||
7940 hrqrule->action_ptr != http_action_res_capture_by_id)
7941 continue;
7942
7943 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7944 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7945 curproxy->id, hrqrule->arg.capid.idx);
7946 cfgerr++;
7947 }
7948 }
7949
Willy Tarreau09448f72014-06-25 18:12:15 +02007950 /* find the target table for 'http-request' layer 7 rules */
7951 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7952 struct proxy *target;
7953
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007954 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007955 continue;
7956
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007957 if (hrqrule->arg.trk_ctr.table.n)
7958 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007959 else
7960 target = curproxy;
7961
7962 if (!target) {
7963 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007964 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007965 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007966 cfgerr++;
7967 }
7968 else if (target->table.size == 0) {
7969 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007970 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007971 cfgerr++;
7972 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007973 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007974 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007975 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007976 http_trk_idx(hrqrule->action));
7977 cfgerr++;
7978 }
7979 else {
7980 free(hrqrule->arg.trk_ctr.table.n);
7981 hrqrule->arg.trk_ctr.table.t = &target->table;
7982 /* Note: if we decide to enhance the track-sc syntax, we may be able
7983 * to pass a list of counters to track and allocate them right here using
7984 * stktable_alloc_data_type().
7985 */
7986 }
7987 }
7988
7989 /* find the target table for 'http-response' layer 7 rules */
7990 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7991 struct proxy *target;
7992
7993 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7994 continue;
7995
7996 if (hrqrule->arg.trk_ctr.table.n)
7997 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7998 else
7999 target = curproxy;
8000
8001 if (!target) {
8002 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8003 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8004 http_trk_idx(hrqrule->action));
8005 cfgerr++;
8006 }
8007 else if (target->table.size == 0) {
8008 Alert("Proxy '%s': table '%s' used but not configured.\n",
8009 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8010 cfgerr++;
8011 }
8012 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8013 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8014 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8015 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008016 cfgerr++;
8017 }
8018 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008019 free(hrqrule->arg.trk_ctr.table.n);
8020 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008021 /* Note: if we decide to enhance the track-sc syntax, we may be able
8022 * to pass a list of counters to track and allocate them right here using
8023 * stktable_alloc_data_type().
8024 */
8025 }
8026 }
8027
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008028 /* move any "block" rules at the beginning of the http-request rules */
8029 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8030 /* insert block_rules into http_req_rules at the beginning */
8031 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8032 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8033 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8034 curproxy->http_req_rules.n = curproxy->block_rules.n;
8035 LIST_INIT(&curproxy->block_rules);
8036 }
8037
Emeric Brun32da3c42010-09-23 18:39:19 +02008038 if (curproxy->table.peers.name) {
8039 struct peers *curpeers = peers;
8040
8041 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8042 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8043 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008044 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008045 break;
8046 }
8047 }
8048
8049 if (!curpeers) {
8050 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8051 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008052 free((void *)curproxy->table.peers.name);
8053 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008054 cfgerr++;
8055 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008056 else if (curpeers->state == PR_STSTOPPED) {
8057 /* silently disable this peers section */
8058 curproxy->table.peers.p = NULL;
8059 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008060 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008061 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8062 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008063 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008064 cfgerr++;
8065 }
8066 }
8067
Simon Horman9dc49962015-01-30 11:22:59 +09008068
8069 if (curproxy->email_alert.mailers.name) {
8070 struct mailers *curmailers = mailers;
8071
8072 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8073 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8074 free(curproxy->email_alert.mailers.name);
8075 curproxy->email_alert.mailers.m = curmailers;
8076 curmailers->users++;
8077 break;
8078 }
8079 }
8080
8081 if (!curmailers) {
8082 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8083 curproxy->id, curproxy->email_alert.mailers.name);
8084 free_email_alert(curproxy);
8085 cfgerr++;
8086 }
8087 }
8088
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008089 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008090 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008091 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8092 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8093 "proxy", curproxy->id);
8094 cfgerr++;
8095 goto out_uri_auth_compat;
8096 }
8097
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008098 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008099 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008100 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008101 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008102
Willy Tarreau95fa4692010-02-01 13:05:50 +01008103 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8104 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008105
8106 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008107 uri_auth_compat_req[i++] = "realm";
8108 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8109 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008110
Willy Tarreau95fa4692010-02-01 13:05:50 +01008111 uri_auth_compat_req[i++] = "unless";
8112 uri_auth_compat_req[i++] = "{";
8113 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8114 uri_auth_compat_req[i++] = "}";
8115 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008116
Willy Tarreauff011f22011-01-06 17:51:27 +01008117 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8118 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008119 cfgerr++;
8120 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008121 }
8122
Willy Tarreauff011f22011-01-06 17:51:27 +01008123 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008124
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008125 if (curproxy->uri_auth->auth_realm) {
8126 free(curproxy->uri_auth->auth_realm);
8127 curproxy->uri_auth->auth_realm = NULL;
8128 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008129
8130 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008131 }
8132out_uri_auth_compat:
8133
Dragan Dosen43885c72015-10-01 13:18:13 +02008134 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008135 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008136 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8137 if (!curproxy->conf.logformat_sd_string) {
8138 /* set the default logformat_sd_string */
8139 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8140 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008141 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008142 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008143 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008144
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008145 /* compile the log format */
8146 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008147 if (curproxy->conf.logformat_string != default_http_log_format &&
8148 curproxy->conf.logformat_string != default_tcp_log_format &&
8149 curproxy->conf.logformat_string != clf_http_log_format)
8150 free(curproxy->conf.logformat_string);
8151 curproxy->conf.logformat_string = NULL;
8152 free(curproxy->conf.lfs_file);
8153 curproxy->conf.lfs_file = NULL;
8154 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008155
8156 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8157 free(curproxy->conf.logformat_sd_string);
8158 curproxy->conf.logformat_sd_string = NULL;
8159 free(curproxy->conf.lfsd_file);
8160 curproxy->conf.lfsd_file = NULL;
8161 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008162 }
8163
Willy Tarreau62a61232013-04-12 18:13:46 +02008164 if (curproxy->conf.logformat_string) {
8165 curproxy->conf.args.ctx = ARGC_LOG;
8166 curproxy->conf.args.file = curproxy->conf.lfs_file;
8167 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008168 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008169 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008170 SMP_VAL_FE_LOG_END, &err)) {
8171 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8172 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8173 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008174 cfgerr++;
8175 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008176 curproxy->conf.args.file = NULL;
8177 curproxy->conf.args.line = 0;
8178 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008179
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008180 if (curproxy->conf.logformat_sd_string) {
8181 curproxy->conf.args.ctx = ARGC_LOGSD;
8182 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8183 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008184 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008185 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 +01008186 SMP_VAL_FE_LOG_END, &err)) {
8187 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8188 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8189 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008190 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008191 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8192 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8193 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8194 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008195 cfgerr++;
8196 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008197 curproxy->conf.args.file = NULL;
8198 curproxy->conf.args.line = 0;
8199 }
8200
Willy Tarreau62a61232013-04-12 18:13:46 +02008201 if (curproxy->conf.uniqueid_format_string) {
8202 curproxy->conf.args.ctx = ARGC_UIF;
8203 curproxy->conf.args.file = curproxy->conf.uif_file;
8204 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008205 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008206 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 +01008207 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8208 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8209 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8210 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008211 cfgerr++;
8212 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008213 curproxy->conf.args.file = NULL;
8214 curproxy->conf.args.line = 0;
8215 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008216
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008217 /* only now we can check if some args remain unresolved.
8218 * This must be done after the users and groups resolution.
8219 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008220 cfgerr += smp_resolve_args(curproxy);
8221 if (!cfgerr)
8222 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008223
Willy Tarreau2738a142006-07-08 17:28:09 +02008224 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008225 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008226 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008227 (!curproxy->timeout.connect ||
8228 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008229 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008230 " | While not properly invalid, you will certainly encounter various problems\n"
8231 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008232 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008233 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008234 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008235 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008236
Willy Tarreau1fa31262007-12-03 00:36:16 +01008237 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8238 * We must still support older configurations, so let's find out whether those
8239 * parameters have been set or must be copied from contimeouts.
8240 */
8241 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008242 if (!curproxy->timeout.tarpit ||
8243 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008244 /* tarpit timeout not set. We search in the following order:
8245 * default.tarpit, curr.connect, default.connect.
8246 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008247 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008248 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008249 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008250 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008251 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008252 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008253 }
8254 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008255 (!curproxy->timeout.queue ||
8256 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008257 /* queue timeout not set. We search in the following order:
8258 * default.queue, curr.connect, default.connect.
8259 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008260 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008261 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008262 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008263 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008264 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008265 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008266 }
8267 }
8268
Willy Tarreau1620ec32011-08-06 17:05:02 +02008269 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008270 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008271 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008272 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008273 }
8274
Willy Tarreau215663d2014-06-13 18:30:23 +02008275 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8276 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8277 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8278 proxy_type_str(curproxy), curproxy->id);
8279 err_code |= ERR_WARN;
8280 }
8281
Willy Tarreau193b8c62012-11-22 00:17:38 +01008282 /* ensure that cookie capture length is not too large */
8283 if (curproxy->capture_len >= global.tune.cookie_len) {
8284 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8285 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8286 err_code |= ERR_WARN;
8287 curproxy->capture_len = global.tune.cookie_len - 1;
8288 }
8289
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008290 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008291 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008292 curproxy->req_cap_pool = create_pool("ptrcap",
8293 curproxy->nb_req_cap * sizeof(char *),
8294 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008295 }
8296
8297 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008298 curproxy->rsp_cap_pool = create_pool("ptrcap",
8299 curproxy->nb_rsp_cap * sizeof(char *),
8300 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008301 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008302
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008303 switch (curproxy->load_server_state_from_file) {
8304 case PR_SRV_STATE_FILE_UNSPEC:
8305 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8306 break;
8307 case PR_SRV_STATE_FILE_GLOBAL:
8308 if (!global.server_state_file) {
8309 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",
8310 curproxy->id);
8311 err_code |= ERR_WARN;
8312 }
8313 break;
8314 }
8315
Willy Tarreaubaaee002006-06-26 02:48:02 +02008316 /* first, we will invert the servers list order */
8317 newsrv = NULL;
8318 while (curproxy->srv) {
8319 struct server *next;
8320
8321 next = curproxy->srv->next;
8322 curproxy->srv->next = newsrv;
8323 newsrv = curproxy->srv;
8324 if (!next)
8325 break;
8326 curproxy->srv = next;
8327 }
8328
Willy Tarreau17edc812014-01-03 12:14:34 +01008329 /* Check that no server name conflicts. This causes trouble in the stats.
8330 * We only emit a warning for the first conflict affecting each server,
8331 * in order to avoid combinatory explosion if all servers have the same
8332 * name. We do that only for servers which do not have an explicit ID,
8333 * because these IDs were made also for distinguishing them and we don't
8334 * want to annoy people who correctly manage them.
8335 */
8336 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8337 struct server *other_srv;
8338
8339 if (newsrv->puid)
8340 continue;
8341
8342 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8343 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8344 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8345 newsrv->conf.file, newsrv->conf.line,
8346 proxy_type_str(curproxy), curproxy->id,
8347 newsrv->id, other_srv->conf.line);
8348 break;
8349 }
8350 }
8351 }
8352
Willy Tarreaudd701652010-05-25 23:03:02 +02008353 /* assign automatic UIDs to servers which don't have one yet */
8354 next_id = 1;
8355 newsrv = curproxy->srv;
8356 while (newsrv != NULL) {
8357 if (!newsrv->puid) {
8358 /* server ID not set, use automatic numbering with first
8359 * spare entry starting with next_svid.
8360 */
8361 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8362 newsrv->conf.id.key = newsrv->puid = next_id;
8363 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8364 }
8365 next_id++;
8366 newsrv = newsrv->next;
8367 }
8368
Willy Tarreau20697042007-11-15 23:26:18 +01008369 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008370 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008371
Willy Tarreau62c3be22012-01-20 13:12:32 +01008372 /*
8373 * If this server supports a maxconn parameter, it needs a dedicated
8374 * tasks to fill the emptied slots when a connection leaves.
8375 * Also, resolve deferred tracking dependency if needed.
8376 */
8377 newsrv = curproxy->srv;
8378 while (newsrv != NULL) {
8379 if (newsrv->minconn > newsrv->maxconn) {
8380 /* Only 'minconn' was specified, or it was higher than or equal
8381 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8382 * this will avoid further useless expensive computations.
8383 */
8384 newsrv->maxconn = newsrv->minconn;
8385 } else if (newsrv->maxconn && !newsrv->minconn) {
8386 /* minconn was not specified, so we set it to maxconn */
8387 newsrv->minconn = newsrv->maxconn;
8388 }
8389
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008390#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008391 if (newsrv->use_ssl || newsrv->check.use_ssl)
8392 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008393#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008394
Willy Tarreau2f075e92013-12-03 11:11:34 +01008395 /* set the check type on the server */
8396 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8397
Willy Tarreau62c3be22012-01-20 13:12:32 +01008398 if (newsrv->trackit) {
8399 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008400 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008401 char *pname, *sname;
8402
8403 pname = newsrv->trackit;
8404 sname = strrchr(pname, '/');
8405
8406 if (sname)
8407 *sname++ = '\0';
8408 else {
8409 sname = pname;
8410 pname = NULL;
8411 }
8412
8413 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008414 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008415 if (!px) {
8416 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8417 proxy_type_str(curproxy), curproxy->id,
8418 newsrv->id, pname);
8419 cfgerr++;
8420 goto next_srv;
8421 }
8422 } else
8423 px = curproxy;
8424
8425 srv = findserver(px, sname);
8426 if (!srv) {
8427 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8428 proxy_type_str(curproxy), curproxy->id,
8429 newsrv->id, sname);
8430 cfgerr++;
8431 goto next_srv;
8432 }
8433
Willy Tarreau32091232014-05-16 13:52:00 +02008434 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8435 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8436 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008437 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008438 "tracking as it does not have any check nor agent enabled.\n",
8439 proxy_type_str(curproxy), curproxy->id,
8440 newsrv->id, px->id, srv->id);
8441 cfgerr++;
8442 goto next_srv;
8443 }
8444
8445 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8446
8447 if (loop) {
8448 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8449 "belongs to a tracking chain looping back to %s/%s.\n",
8450 proxy_type_str(curproxy), curproxy->id,
8451 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008452 cfgerr++;
8453 goto next_srv;
8454 }
8455
8456 if (curproxy != px &&
8457 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8458 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8459 "tracking: disable-on-404 option inconsistency.\n",
8460 proxy_type_str(curproxy), curproxy->id,
8461 newsrv->id, px->id, srv->id);
8462 cfgerr++;
8463 goto next_srv;
8464 }
8465
Willy Tarreau62c3be22012-01-20 13:12:32 +01008466 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008467 newsrv->tracknext = srv->trackers;
8468 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008469
8470 free(newsrv->trackit);
8471 newsrv->trackit = NULL;
8472 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008473
8474 /*
8475 * resolve server's resolvers name and update the resolvers pointer
8476 * accordingly
8477 */
8478 if (newsrv->resolvers_id) {
8479 struct dns_resolvers *curr_resolvers;
8480 int found;
8481
8482 found = 0;
8483 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8484 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8485 found = 1;
8486 break;
8487 }
8488 }
8489
8490 if (!found) {
8491 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8492 proxy_type_str(curproxy), curproxy->id,
8493 newsrv->id, newsrv->resolvers_id);
8494 cfgerr++;
8495 } else {
8496 free(newsrv->resolvers_id);
8497 newsrv->resolvers_id = NULL;
8498 if (newsrv->resolution)
8499 newsrv->resolution->resolvers = curr_resolvers;
8500 }
8501 }
8502 else {
8503 /* if no resolvers section associated to this server
8504 * we can clean up the associated resolution structure
8505 */
8506 if (newsrv->resolution) {
8507 free(newsrv->resolution->hostname_dn);
8508 newsrv->resolution->hostname_dn = NULL;
8509 free(newsrv->resolution);
8510 newsrv->resolution = NULL;
8511 }
8512 }
8513
Willy Tarreau62c3be22012-01-20 13:12:32 +01008514 next_srv:
8515 newsrv = newsrv->next;
8516 }
8517
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008518 /* We have to initialize the server lookup mechanism depending
8519 * on what LB algorithm was choosen.
8520 */
8521
8522 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8523 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8524 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008525 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8526 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8527 init_server_map(curproxy);
8528 } else {
8529 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8530 fwrr_init_server_groups(curproxy);
8531 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008532 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008533
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008534 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008535 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8536 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8537 fwlc_init_server_tree(curproxy);
8538 } else {
8539 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8540 fas_init_server_tree(curproxy);
8541 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008542 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008543
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008544 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008545 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8546 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8547 chash_init_server_tree(curproxy);
8548 } else {
8549 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8550 init_server_map(curproxy);
8551 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008552 break;
8553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008554
8555 if (curproxy->options & PR_O_LOGASAP)
8556 curproxy->to_log &= ~LW_BYTES;
8557
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008558 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008559 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8560 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008561 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8562 proxy_type_str(curproxy), curproxy->id);
8563 err_code |= ERR_WARN;
8564 }
8565
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008566 if (curproxy->mode != PR_MODE_HTTP) {
8567 int optnum;
8568
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008569 if (curproxy->uri_auth) {
8570 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8571 proxy_type_str(curproxy), curproxy->id);
8572 err_code |= ERR_WARN;
8573 curproxy->uri_auth = NULL;
8574 }
8575
Willy Tarreau87cf5142011-08-19 22:57:24 +02008576 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008577 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8578 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8579 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008580 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008581 }
8582
8583 if (curproxy->options & PR_O_ORGTO) {
8584 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8585 "originalto", proxy_type_str(curproxy), curproxy->id);
8586 err_code |= ERR_WARN;
8587 curproxy->options &= ~PR_O_ORGTO;
8588 }
8589
8590 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8591 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8592 (curproxy->cap & cfg_opts[optnum].cap) &&
8593 (curproxy->options & cfg_opts[optnum].val)) {
8594 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8595 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8596 err_code |= ERR_WARN;
8597 curproxy->options &= ~cfg_opts[optnum].val;
8598 }
8599 }
8600
8601 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8602 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8603 (curproxy->cap & cfg_opts2[optnum].cap) &&
8604 (curproxy->options2 & cfg_opts2[optnum].val)) {
8605 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8606 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8607 err_code |= ERR_WARN;
8608 curproxy->options2 &= ~cfg_opts2[optnum].val;
8609 }
8610 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008611
Willy Tarreau29fbe512015-08-20 19:35:14 +02008612#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008613 if (curproxy->conn_src.bind_hdr_occ) {
8614 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008615 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008616 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008617 err_code |= ERR_WARN;
8618 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008619#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008620 }
8621
Willy Tarreaubaaee002006-06-26 02:48:02 +02008622 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008623 * ensure that we're not cross-dressing a TCP server into HTTP.
8624 */
8625 newsrv = curproxy->srv;
8626 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008627 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008628 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8629 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008630 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008631 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008632
Willy Tarreau0cec3312011-10-31 13:49:26 +01008633 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8634 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8635 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8636 err_code |= ERR_WARN;
8637 }
8638
Willy Tarreauc93cd162014-05-13 15:54:22 +02008639 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008640 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8641 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8642 err_code |= ERR_WARN;
8643 }
8644
Willy Tarreau29fbe512015-08-20 19:35:14 +02008645#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008646 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8647 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008648 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 +01008649 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008650 err_code |= ERR_WARN;
8651 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008652#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008653 newsrv = newsrv->next;
8654 }
8655
Willy Tarreaue42bd962014-09-16 16:21:19 +02008656 /* check if we have a frontend with "tcp-request content" looking at L7
8657 * with no inspect-delay
8658 */
8659 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8660 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008661 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008662 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008663 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008664 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008665 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008666 break;
8667 }
8668
8669 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8670 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8671 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8672 " This means that these rules will randomly find their contents. This can be fixed by"
8673 " setting the tcp-request inspect-delay.\n",
8674 proxy_type_str(curproxy), curproxy->id);
8675 err_code |= ERR_WARN;
8676 }
8677 }
8678
Christopher Fauletd7c91962015-04-30 11:48:27 +02008679 /* Check filter configuration, if any */
8680 cfgerr += flt_check(curproxy);
8681
Willy Tarreauc1a21672009-08-16 22:37:44 +02008682 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008683 if (!curproxy->accept)
8684 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008685
Willy Tarreauc1a21672009-08-16 22:37:44 +02008686 if (curproxy->tcp_req.inspect_delay ||
8687 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008688 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008689
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008690 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008691 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008692 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008693 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008694
8695 /* both TCP and HTTP must check switching rules */
8696 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008697
8698 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008699 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008700 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8701 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008702 if (curproxy->mode == PR_MODE_HTTP) {
8703 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8704 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8705 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008706 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008707 }
8708
8709 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008710 if (curproxy->tcp_req.inspect_delay ||
8711 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8712 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8713
Emeric Brun97679e72010-09-23 17:56:44 +02008714 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8715 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8716
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008717 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008718 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008719 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008720 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008721
8722 /* If the backend does requires RDP cookie persistence, we have to
8723 * enable the corresponding analyser.
8724 */
8725 if (curproxy->options2 & PR_O2_RDPC_PRST)
8726 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008727
8728 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008729 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008730 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8731 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008732 if (curproxy->mode == PR_MODE_HTTP) {
8733 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8734 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8735 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008736 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008737 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008738 }
8739
8740 /***********************************************************/
8741 /* At this point, target names have already been resolved. */
8742 /***********************************************************/
8743
8744 /* Check multi-process mode compatibility */
8745
8746 if (global.nbproc > 1 && global.stats_fe) {
8747 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8748 unsigned long mask;
8749
8750 mask = nbits(global.nbproc);
8751 if (global.stats_fe->bind_proc)
8752 mask &= global.stats_fe->bind_proc;
8753
8754 if (bind_conf->bind_proc)
8755 mask &= bind_conf->bind_proc;
8756
8757 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008758 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008759 break;
8760 }
8761 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8762 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");
8763 }
8764 }
8765
8766 /* Make each frontend inherit bind-process from its listeners when not specified. */
8767 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8768 if (curproxy->bind_proc)
8769 continue;
8770
8771 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8772 unsigned long mask;
8773
Willy Tarreaue428b082015-05-04 21:57:58 +02008774 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008775 curproxy->bind_proc |= mask;
8776 }
8777
8778 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008779 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008780 }
8781
8782 if (global.stats_fe) {
8783 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8784 unsigned long mask;
8785
Cyril Bonté06181952016-02-24 00:14:54 +01008786 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008787 global.stats_fe->bind_proc |= mask;
8788 }
8789 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008790 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008791 }
8792
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008793 /* propagate bindings from frontends to backends. Don't do it if there
8794 * are any fatal errors as we must not call it with unresolved proxies.
8795 */
8796 if (!cfgerr) {
8797 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8798 if (curproxy->cap & PR_CAP_FE)
8799 propagate_processes(curproxy, NULL);
8800 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008801 }
8802
8803 /* Bind each unbound backend to all processes when not specified. */
8804 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8805 if (curproxy->bind_proc)
8806 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008807 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008808 }
8809
8810 /*******************************************************/
8811 /* At this step, all proxies have a non-null bind_proc */
8812 /*******************************************************/
8813
8814 /* perform the final checks before creating tasks */
8815
8816 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8817 struct listener *listener;
8818 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008819
Emeric Brunc52962f2012-11-15 18:28:02 +01008820#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008821 /* Configure SSL for each bind line.
8822 * Note: if configuration fails at some point, the ->ctx member
8823 * remains NULL so that listeners can later detach.
8824 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008825 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008826 int alloc_ctx;
8827
Emeric Brunc52962f2012-11-15 18:28:02 +01008828 if (!bind_conf->is_ssl) {
8829 if (bind_conf->default_ctx) {
8830 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8831 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8832 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008833 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008834 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008835 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008836 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008837 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008838 cfgerr++;
8839 continue;
8840 }
8841
Emeric Brun8dc60392014-05-09 13:52:00 +02008842 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008843 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008844 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8845 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");
8846 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008847 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008848 cfgerr++;
8849 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008850 }
8851
Emeric Brunfc0421f2012-09-07 17:30:07 +02008852 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008853 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008854
8855 /* initialize CA variables if the certificates generation is enabled */
8856 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008857 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008858#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008859
Willy Tarreaue6b98942007-10-29 01:09:36 +01008860 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008861 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008862 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008863 int nbproc;
8864
8865 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008866 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008867 nbits(global.nbproc));
8868
8869 if (!nbproc) /* no intersection between listener and frontend */
8870 nbproc = 1;
8871
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008872 if (!listener->luid) {
8873 /* listener ID not set, use automatic numbering with first
8874 * spare entry starting with next_luid.
8875 */
8876 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8877 listener->conf.id.key = listener->luid = next_id;
8878 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008879 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008880 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008881
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008882 /* enable separate counters */
8883 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008884 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008885 if (!listener->name)
8886 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008887 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008888
Willy Tarreaue6b98942007-10-29 01:09:36 +01008889 if (curproxy->options & PR_O_TCP_NOLING)
8890 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008891 if (!listener->maxconn)
8892 listener->maxconn = curproxy->maxconn;
8893 if (!listener->backlog)
8894 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008895 if (!listener->maxaccept)
8896 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8897
8898 /* we want to have an optimal behaviour on single process mode to
8899 * maximize the work at once, but in multi-process we want to keep
8900 * some fairness between processes, so we target half of the max
8901 * number of events to be balanced over all the processes the proxy
8902 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8903 * used to disable the limit.
8904 */
8905 if (listener->maxaccept > 0) {
8906 if (nbproc > 1)
8907 listener->maxaccept = (listener->maxaccept + 1) / 2;
8908 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8909 }
8910
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008911 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008912 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008913 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008914 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008915
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008916 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008917 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008918
Willy Tarreau620408f2016-10-21 16:37:51 +02008919 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8920 listener->options |= LI_O_TCP_L5_RULES;
8921
Willy Tarreaude3041d2010-05-31 10:56:17 +02008922 if (curproxy->mon_mask.s_addr)
8923 listener->options |= LI_O_CHK_MONNET;
8924
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008925 /* smart accept mode is automatic in HTTP mode */
8926 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008927 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008928 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8929 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008930 }
8931
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008932 /* Release unused SSL configs */
8933 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8934 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008935 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008936#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008937 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008938 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008939 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008940 free(bind_conf->ca_sign_file);
8941 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008942 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008943 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008944 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008945 if(bind_conf->keys_ref) {
8946 free(bind_conf->keys_ref->filename);
8947 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02008948 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008949 free(bind_conf->keys_ref);
8950 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008951#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008952 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008953
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008954 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008955 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008956 int count, maxproc = 0;
8957
8958 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008959 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008960 if (count > maxproc)
8961 maxproc = count;
8962 }
8963 /* backends have 0, frontends have 1 or more */
8964 if (maxproc != 1)
8965 Warning("Proxy '%s': in multi-process mode, stats will be"
8966 " limited to process assigned to the current request.\n",
8967 curproxy->id);
8968
Willy Tarreau102df612014-05-07 23:56:38 +02008969 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8970 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8971 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008972 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008973 }
Willy Tarreau102df612014-05-07 23:56:38 +02008974 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8975 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8976 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008977 }
8978 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008979
8980 /* create the task associated with the proxy */
8981 curproxy->task = task_new();
8982 if (curproxy->task) {
8983 curproxy->task->context = curproxy;
8984 curproxy->task->process = manage_proxy;
8985 /* no need to queue, it will be done automatically if some
8986 * listener gets limited.
8987 */
8988 curproxy->task->expire = TICK_ETERNITY;
8989 } else {
8990 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8991 curproxy->id);
8992 cfgerr++;
8993 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008994 }
8995
Willy Tarreaufbb78422011-06-05 15:38:35 +02008996 /* automatically compute fullconn if not set. We must not do it in the
8997 * loop above because cross-references are not yet fully resolved.
8998 */
8999 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9000 /* If <fullconn> is not set, let's set it to 10% of the sum of
9001 * the possible incoming frontend's maxconns.
9002 */
9003 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9004 struct proxy *fe;
9005 int total = 0;
9006
9007 /* sum up the number of maxconns of frontends which
9008 * reference this backend at least once or which are
9009 * the same one ('listen').
9010 */
9011 for (fe = proxy; fe; fe = fe->next) {
9012 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009013 int found = 0;
9014
9015 if (!(fe->cap & PR_CAP_FE))
9016 continue;
9017
9018 if (fe == curproxy) /* we're on a "listen" instance */
9019 found = 1;
9020
9021 if (fe->defbe.be == curproxy) /* "default_backend" */
9022 found = 1;
9023
9024 /* check if a "use_backend" rule matches */
9025 if (!found) {
9026 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009027 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009028 found = 1;
9029 break;
9030 }
9031 }
9032 }
9033
Willy Tarreaufbb78422011-06-05 15:38:35 +02009034 /* now we've checked all possible ways to reference a backend
9035 * from a frontend.
9036 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009037 if (!found)
9038 continue;
9039 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009040 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009041 /* we have the sum of the maxconns in <total>. We only
9042 * keep 10% of that sum to set the default fullconn, with
9043 * a hard minimum of 1 (to avoid a divide by zero).
9044 */
9045 curproxy->fullconn = (total + 9) / 10;
9046 if (!curproxy->fullconn)
9047 curproxy->fullconn = 1;
9048 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009049 }
9050
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009051 /*
9052 * Recount currently required checks.
9053 */
9054
9055 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9056 int optnum;
9057
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009058 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9059 if (curproxy->options & cfg_opts[optnum].val)
9060 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009061
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009062 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9063 if (curproxy->options2 & cfg_opts2[optnum].val)
9064 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009065 }
9066
Willy Tarreau0fca4832015-05-01 19:12:05 +02009067 /* compute the required process bindings for the peers */
9068 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9069 if (curproxy->table.peers.p)
9070 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9071
Willy Tarreau122541c2011-09-07 21:24:49 +02009072 if (peers) {
9073 struct peers *curpeers = peers, **last;
9074 struct peer *p, *pb;
9075
Willy Tarreau1e273012015-05-01 19:15:17 +02009076 /* Remove all peers sections which don't have a valid listener,
9077 * which are not used by any table, or which are bound to more
9078 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009079 */
9080 last = &peers;
9081 while (*last) {
9082 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009083
9084 if (curpeers->state == PR_STSTOPPED) {
9085 /* the "disabled" keyword was present */
9086 if (curpeers->peers_fe)
9087 stop_proxy(curpeers->peers_fe);
9088 curpeers->peers_fe = NULL;
9089 }
9090 else if (!curpeers->peers_fe) {
9091 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9092 curpeers->id, localpeer);
9093 }
David Carliere6c39412015-07-02 07:00:17 +00009094 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009095 /* either it's totally stopped or too much used */
9096 if (curpeers->peers_fe->bind_proc) {
9097 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009098 "running in different processes (%d different ones). "
9099 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009100 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009101 cfgerr++;
9102 }
9103 stop_proxy(curpeers->peers_fe);
9104 curpeers->peers_fe = NULL;
9105 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009106 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009107 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009108 last = &curpeers->next;
9109 continue;
9110 }
9111
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009112 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009113 p = curpeers->remote;
9114 while (p) {
9115 pb = p->next;
9116 free(p->id);
9117 free(p);
9118 p = pb;
9119 }
9120
9121 /* Destroy and unlink this curpeers section.
9122 * Note: curpeers is backed up into *last.
9123 */
9124 free(curpeers->id);
9125 curpeers = curpeers->next;
9126 free(*last);
9127 *last = curpeers;
9128 }
9129 }
9130
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009131 /* initialize stick-tables on backend capable proxies. This must not
9132 * be done earlier because the data size may be discovered while parsing
9133 * other proxies.
9134 */
9135 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9136 if (curproxy->state == PR_STSTOPPED)
9137 continue;
9138
9139 if (!stktable_init(&curproxy->table)) {
9140 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9141 cfgerr++;
9142 }
9143 }
9144
Simon Horman0d16a402015-01-30 11:22:58 +09009145 if (mailers) {
9146 struct mailers *curmailers = mailers, **last;
9147 struct mailer *m, *mb;
9148
9149 /* Remove all mailers sections which don't have a valid listener.
9150 * This can happen when a mailers section is never referenced.
9151 */
9152 last = &mailers;
9153 while (*last) {
9154 curmailers = *last;
9155 if (curmailers->users) {
9156 last = &curmailers->next;
9157 continue;
9158 }
9159
9160 Warning("Removing incomplete section 'mailers %s'.\n",
9161 curmailers->id);
9162
9163 m = curmailers->mailer_list;
9164 while (m) {
9165 mb = m->next;
9166 free(m->id);
9167 free(m);
9168 m = mb;
9169 }
9170
9171 /* Destroy and unlink this curmailers section.
9172 * Note: curmailers is backed up into *last.
9173 */
9174 free(curmailers->id);
9175 curmailers = curmailers->next;
9176 free(*last);
9177 *last = curmailers;
9178 }
9179 }
9180
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009181 /* Update server_state_file_name to backend name if backend is supposed to use
9182 * a server-state file locally defined and none has been provided */
9183 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9184 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9185 curproxy->server_state_file_name == NULL)
9186 curproxy->server_state_file_name = strdup(curproxy->id);
9187 }
9188
Willy Tarreau34eb6712011-10-24 18:15:04 +02009189 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009190 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009191 MEM_F_SHARED);
9192
Willy Tarreaubb925012009-07-23 13:36:36 +02009193 if (cfgerr > 0)
9194 err_code |= ERR_ALERT | ERR_FATAL;
9195 out:
9196 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009197}
9198
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009199/*
9200 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9201 * parsing sessions.
9202 */
9203void cfg_register_keywords(struct cfg_kw_list *kwl)
9204{
9205 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9206}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009207
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009208/*
9209 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9210 */
9211void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9212{
9213 LIST_DEL(&kwl->list);
9214 LIST_INIT(&kwl->list);
9215}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009216
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009217/* this function register new section in the haproxy configuration file.
9218 * <section_name> is the name of this new section and <section_parser>
9219 * is the called parser. If two section declaration have the same name,
9220 * only the first declared is used.
9221 */
9222int cfg_register_section(char *section_name,
9223 int (*section_parser)(const char *, int, char **, int))
9224{
9225 struct cfg_section *cs;
9226
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009227 list_for_each_entry(cs, &sections, list) {
9228 if (strcmp(cs->section_name, section_name) == 0) {
9229 Alert("register section '%s': already registered.\n", section_name);
9230 return 0;
9231 }
9232 }
9233
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009234 cs = calloc(1, sizeof(*cs));
9235 if (!cs) {
9236 Alert("register section '%s': out of memory.\n", section_name);
9237 return 0;
9238 }
9239
9240 cs->section_name = section_name;
9241 cs->section_parser = section_parser;
9242
9243 LIST_ADDQ(&sections, &cs->list);
9244
9245 return 1;
9246}
9247
Willy Tarreaubaaee002006-06-26 02:48:02 +02009248/*
David Carlier845efb52015-09-25 11:49:18 +01009249 * free all config section entries
9250 */
9251void cfg_unregister_sections(void)
9252{
9253 struct cfg_section *cs, *ics;
9254
9255 list_for_each_entry_safe(cs, ics, &sections, list) {
9256 LIST_DEL(&cs->list);
9257 free(cs);
9258 }
9259}
9260
Christopher Faulet7110b402016-10-26 11:09:44 +02009261void cfg_backup_sections(struct list *backup_sections)
9262{
9263 struct cfg_section *cs, *ics;
9264
9265 list_for_each_entry_safe(cs, ics, &sections, list) {
9266 LIST_DEL(&cs->list);
9267 LIST_ADDQ(backup_sections, &cs->list);
9268 }
9269}
9270
9271void cfg_restore_sections(struct list *backup_sections)
9272{
9273 struct cfg_section *cs, *ics;
9274
9275 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9276 LIST_DEL(&cs->list);
9277 LIST_ADDQ(&sections, &cs->list);
9278 }
9279}
9280
Willy Tarreau659fbf02016-05-26 17:55:28 +02009281__attribute__((constructor))
9282static void cfgparse_init(void)
9283{
9284 /* Register internal sections */
9285 cfg_register_section("listen", cfg_parse_listen);
9286 cfg_register_section("frontend", cfg_parse_listen);
9287 cfg_register_section("backend", cfg_parse_listen);
9288 cfg_register_section("defaults", cfg_parse_listen);
9289 cfg_register_section("global", cfg_parse_global);
9290 cfg_register_section("userlist", cfg_parse_users);
9291 cfg_register_section("peers", cfg_parse_peers);
9292 cfg_register_section("mailers", cfg_parse_mailers);
9293 cfg_register_section("namespace_list", cfg_parse_netns);
9294 cfg_register_section("resolvers", cfg_parse_resolvers);
9295}
9296
David Carlier845efb52015-09-25 11:49:18 +01009297/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009298 * Local variables:
9299 * c-indent-level: 8
9300 * c-basic-offset: 8
9301 * End:
9302 */