blob: 17f9d19a4301adc552e04b45f4d63debef3fdc87 [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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054
Willy Tarreaueb0c6142007-05-07 00:53:22 +020055#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010056#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020058#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020060#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020061#include <proto/dumpstats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020062#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020063#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020064#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020065#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010066#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020067#include <proto/lb_fwlc.h>
68#include <proto/lb_fwrr.h>
69#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020071#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020074#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010076#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020077#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020078#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020079#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020081#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020082#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Emeric Brunfc0421f2012-09-07 17:30:07 +020086#ifdef USE_OPENSSL
87#include <types/ssl_sock.h>
88#include <proto/ssl_sock.h>
89#include <proto/shctx.h>
90#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020091
Willy Tarreauf3c69202006-07-09 16:42:34 +020092/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
93 * ssl-hello-chk option to ensure that the remote server speaks SSL.
94 *
95 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
96 */
97const char sslv3_client_hello_pkt[] = {
98 "\x16" /* ContentType : 0x16 = Hanshake */
99 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
100 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
101 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
102 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
103 "\x03\x00" /* Hello Version : 0x0300 = v3 */
104 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
105 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
106 "\x00" /* Session ID length : empty (no session ID) */
107 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
108 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
109 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
110 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
111 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
112 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
113 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
114 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
115 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
116 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
117 "\x00\x38" "\x00\x39" "\x00\x3A"
118 "\x01" /* Compression Length : 0x01 = 1 byte for types */
119 "\x00" /* Compression Type : 0x00 = NULL compression */
120};
121
Willy Tarreau3842f002009-06-14 11:39:52 +0200122/* various keyword modifiers */
123enum kw_mod {
124 KWM_STD = 0, /* normal */
125 KWM_NO, /* "no" prefixed before the keyword */
126 KWM_DEF, /* "default" prefixed before the keyword */
127};
128
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100129/* permit to store configuration section */
130struct cfg_section {
131 struct list list;
132 char *section_name;
133 int (*section_parser)(const char *, int, char **, int);
134};
135
136/* Used to chain configuration sections definitions. This list
137 * stores struct cfg_section
138 */
139struct list sections = LIST_HEAD_INIT(sections);
140
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100143 const char *name;
144 unsigned int val;
145 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100146 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148};
149
150/* proxy->options */
151static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100152{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
154 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
155 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
157 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
158 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200160 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200161 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100162 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
164 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
165 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100167#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100169#else
170 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100171#endif
172
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100174};
175
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176/* proxy->options2 */
177static const struct cfg_opt cfg_opts2[] =
178{
179#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100180 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
181 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100183#else
184 { "splice-request", 0, 0, 0, 0 },
185 { "splice-response", 0, 0, 0, 0 },
186 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100187#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
189 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
190 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
191 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
192 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
193 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
194 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
196 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400197 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100198 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200199 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200200 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100201 { NULL, 0, 0, 0 }
202};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203
Willy Tarreau6daf3432008-01-22 16:44:08 +0100204static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
206int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100207int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200209/* List head of all known configuration keywords */
210static struct cfg_kw_list cfg_keywords = {
211 .list = LIST_HEAD_INIT(cfg_keywords.list)
212};
213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214/*
215 * converts <str> to a list of listeners which are dynamically allocated.
216 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
217 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
218 * - <port> is a numerical port from 1 to 65535 ;
219 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
220 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
222 * not NULL, it must be a valid pointer to either NULL or a freeable area that
223 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225int 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 +0200226{
227 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 int port, end;
230
231 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200232
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100234 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100235 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
237 str = next;
238 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100239 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 *next++ = 0;
241 }
242
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200244 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200245 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (!ss2)
247 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100249 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100250 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200251 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100255 if (!port || !end) {
256 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
257 goto fail;
258 }
259
Emeric Bruned760922010-10-22 17:59:25 +0200260 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
264
265 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200266 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200267 goto fail;
268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100270 else if (ss2->ss_family == AF_UNSPEC) {
271 socklen_t addr_len;
272
273 /* We want to attach to an already bound fd whose number
274 * is in the addr part of ss2 when cast to sockaddr_in.
275 * Note that by definition there is a single listener.
276 * We still have to determine the address family to
277 * register the correct protocol.
278 */
279 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
280 addr_len = sizeof(*ss2);
281 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
282 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
283 goto fail;
284 }
285
286 port = end = get_host_port(ss2);
287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200290 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100291
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200293 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100294 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
296 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
297 l->frontend = curproxy;
298 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299
Willy Tarreau40aa0702013-03-10 23:51:38 +0100300 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200301 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200302 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 l->state = LI_INIT;
304
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100305 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100307 tcpv4_add_listener(l);
308 }
Emeric Bruned760922010-10-22 17:59:25 +0200309 else if (ss.ss_family == AF_INET6) {
310 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
311 tcpv6_add_listener(l);
312 }
313 else {
Emeric Bruned760922010-10-22 17:59:25 +0200314 uxst_add_listener(l);
315 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200317 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100318 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 } /* end for(port) */
320 } /* end while(next) */
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 fail:
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
William Lallemand6e62fb62015-04-28 16:55:23 +0200328/*
329 * Report a fatal Alert when there is too much arguments
330 * The index is the current keyword in args
331 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
332 * Fill err_code with an ERR_ALERT and an ERR_FATAL
333 */
334int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
335{
336 char *kw = NULL;
337 int i;
338
339 if (!*args[index + maxarg + 1])
340 return 0;
341
342 memprintf(&kw, "%s", args[0]);
343 for (i = 1; i <= index; i++) {
344 memprintf(&kw, "%s %s", kw, args[i]);
345 }
346
347 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
348 free(kw);
349 *err_code |= ERR_ALERT | ERR_FATAL;
350 return 1;
351}
352
353/*
354 * same as alertif_too_many_args_idx with a 0 index
355 */
356int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
357{
358 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
359}
360
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request content' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau61d18892009-03-31 10:49:21 +0200374/* Report a warning if a rule is placed after a 'block' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200379 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau5002f572014-04-23 01:32:02 +0200387/* Report a warning if a rule is placed after an 'http_request' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
390int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
391{
392 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
393 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau61d18892009-03-31 10:49:21 +0200400/* Report a warning if a rule is placed after a reqrewrite rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 if (proxy->req_exp) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
413/* Report a warning if a rule is placed after a reqadd rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100418 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
426/* Report a warning if a rule is placed after a redirect rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
433 file, line, arg);
434 return 1;
435 }
436 return 0;
437}
438
439/* Report a warning if a rule is placed after a 'use_backend' rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
Willy Tarreauee445d92014-04-23 01:39:04 +0200452/* Report a warning if a rule is placed after a 'use-server' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
455int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
456{
457 if (!LIST_ISEMPTY(&proxy->server_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200465/* report a warning if a "tcp request connection" rule is dangerously placed */
466int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
467{
468 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
469 warnif_rule_after_block(proxy, file, line, arg) ||
470 warnif_rule_after_http_req(proxy, file, line, arg) ||
471 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
472 warnif_rule_after_reqadd(proxy, file, line, arg) ||
473 warnif_rule_after_redirect(proxy, file, line, arg) ||
474 warnif_rule_after_use_backend(proxy, file, line, arg) ||
475 warnif_rule_after_use_server(proxy, file, line, arg);
476}
477
478/* report a warning if a "tcp request content" rule is dangerously placed */
479int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
480{
481 return warnif_rule_after_block(proxy, file, line, arg) ||
482 warnif_rule_after_http_req(proxy, file, line, arg) ||
483 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
484 warnif_rule_after_reqadd(proxy, file, line, arg) ||
485 warnif_rule_after_redirect(proxy, file, line, arg) ||
486 warnif_rule_after_use_backend(proxy, file, line, arg) ||
487 warnif_rule_after_use_server(proxy, file, line, arg);
488}
489
Willy Tarreau61d18892009-03-31 10:49:21 +0200490/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100491int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200492{
Willy Tarreau5002f572014-04-23 01:32:02 +0200493 return warnif_rule_after_http_req(proxy, file, line, arg) ||
494 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
495 warnif_rule_after_reqadd(proxy, file, line, arg) ||
496 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200497 warnif_rule_after_use_backend(proxy, file, line, arg) ||
498 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200499}
500
501/* report a warning if an http-request rule is dangerously placed */
502int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
503{
Willy Tarreau61d18892009-03-31 10:49:21 +0200504 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
505 warnif_rule_after_reqadd(proxy, file, line, arg) ||
506 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200507 warnif_rule_after_use_backend(proxy, file, line, arg) ||
508 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200509}
510
511/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100512int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200513{
514 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
515 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200516 warnif_rule_after_use_backend(proxy, file, line, arg) ||
517 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200518}
519
520/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100521int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200522{
523 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200524 warnif_rule_after_use_backend(proxy, file, line, arg) ||
525 warnif_rule_after_use_server(proxy, file, line, arg);
526}
527
528/* report a warning if a redirect rule is dangerously placed */
529int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
530{
531 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
532 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100535/* Report it if a request ACL condition uses some keywords that are incompatible
536 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
537 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
538 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200543 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100545 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100546 return 0;
547
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100548 acl = acl_cond_conflicts(cond, where);
549 if (acl) {
550 if (acl->name && *acl->name)
551 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
552 file, line, acl->name, sample_ckp_names(where));
553 else
554 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 +0200555 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556 return ERR_WARN;
557 }
558 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100559 return 0;
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 if (acl->name && *acl->name)
562 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200563 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100564 else
565 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200566 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100567 return ERR_WARN;
568}
569
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200571 * parse a line in a <global> section. Returns the error code, 0 if OK, or
572 * any combination of :
573 * - ERR_ABORT: must abort ASAP
574 * - ERR_FATAL: we can continue parsing but not start the service
575 * - ERR_WARN: a warning has been emitted
576 * - ERR_ALERT: an alert has been emitted
577 * Only the two first ones can stop processing, the two others are just
578 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200580int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581{
Willy Tarreau058e9072009-07-20 09:30:05 +0200582 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200583 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584
585 if (!strcmp(args[0], "global")) { /* new section */
586 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200587 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 else if (!strcmp(args[0], "ca-base")) {
591#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200592 if(alertif_too_many_args(1, file, linenum, args, &err_code))
593 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200594 if (global.ca_base != NULL) {
595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT;
597 goto out;
598 }
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.ca_base = strdup(args[1]);
605#else
606 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
609#endif
610 }
611 else if (!strcmp(args[0], "crt-base")) {
612#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
614 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200615 if (global.crt_base != NULL) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT;
618 goto out;
619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 global.crt_base = strdup(args[1]);
626#else
627 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630#endif
631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 global.mode |= MODE_DAEMON;
636 }
637 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 global.mode |= MODE_DEBUG;
641 }
642 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100657 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100660 global.tune.options &= ~GTUNE_USE_SPLICE;
661 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200662 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200665 global.tune.options &= ~GTUNE_USE_GAI;
666 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000667 else if (!strcmp(args[0], "noreuseport")) {
668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
670 global.tune.options &= ~GTUNE_USE_REUSEPORT;
671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200673 if (alertif_too_many_args(0, file, linenum, args, &err_code))
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 global.mode |= MODE_QUIET;
676 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200677 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200678 if (alertif_too_many_args(1, file, linenum, args, &err_code))
679 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200680 if (global.tune.maxpollevents != 0) {
681 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT;
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 }
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200689 }
690 global.tune.maxpollevents = atol(args[1]);
691 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100692 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200693 if (alertif_too_many_args(1, file, linenum, args, &err_code))
694 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100695 if (global.tune.maxaccept != 0) {
696 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT;
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 }
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100704 }
705 global.tune.maxaccept = atol(args[1]);
706 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200707 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
709 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 global.tune.chksize = atol(args[1]);
716 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100717 else if (!strcmp(args[0], "tune.recv_enough")) {
718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
719 goto out;
720 if (*(args[1]) == 0) {
721 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
722 err_code |= ERR_ALERT | ERR_FATAL;
723 goto out;
724 }
725 global.tune.recv_enough = atol(args[1]);
726 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200727#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200728 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200729 if (alertif_too_many_args(0, file, linenum, args, &err_code))
730 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200731 global.tune.sslprivatecache = 1;
732 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100733 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741 global.tune.sslcachesize = atol(args[1]);
742 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100743 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
744 unsigned int ssllifetime;
745 const char *res;
746
William Lallemand1a748ae2015-05-19 16:37:23 +0200747 if (alertif_too_many_args(1, file, linenum, args, &err_code))
748 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100749 if (*(args[1]) == 0) {
750 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754
755 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
756 if (res) {
757 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
758 file, linenum, *res, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762
763 global.tune.ssllifetime = ssllifetime;
764 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100765 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200766 if (alertif_too_many_args(1, file, linenum, args, &err_code))
767 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100768 if (*(args[1]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 global.tune.ssl_max_record = atol(args[1]);
774 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200775#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200776 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200777 if (alertif_too_many_args(1, file, linenum, args, &err_code))
778 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
783 }
784 global.tune.ssl_default_dh_param = atol(args[1]);
785 if (global.tune.ssl_default_dh_param < 1024) {
786 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200791#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200792 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.ssl_ctx_cache = atoi(args[1]);
801 if (global.tune.ssl_ctx_cache < 0) {
802 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
803 file, linenum, args[0]);
804 err_code |= ERR_ALERT | ERR_FATAL;
805 goto out;
806 }
807 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200808#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100809 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200810 if (alertif_too_many_args(1, file, linenum, args, &err_code))
811 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.buf_limit = atol(args[1]);
818 if (global.tune.buf_limit) {
819 if (global.tune.buf_limit < 3)
820 global.tune.buf_limit = 3;
821 if (global.tune.buf_limit <= global.tune.reserved_bufs)
822 global.tune.buf_limit = global.tune.reserved_bufs + 1;
823 }
824 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100825 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200826 if (alertif_too_many_args(1, file, linenum, args, &err_code))
827 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.tune.reserved_bufs = atol(args[1]);
834 if (global.tune.reserved_bufs < 2)
835 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100836 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
837 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100838 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200839 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200840 if (alertif_too_many_args(1, file, linenum, args, &err_code))
841 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200848 if (global.tune.bufsize <= 0) {
849 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100853 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100854 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200855 }
856 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200857 if (alertif_too_many_args(1, file, linenum, args, &err_code))
858 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200865 if (global.tune.maxrewrite < 0) {
866 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200870 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100871 else if (!strcmp(args[0], "tune.idletimer")) {
872 unsigned int idle;
873 const char *res;
874
William Lallemand1a748ae2015-05-19 16:37:23 +0200875 if (alertif_too_many_args(1, file, linenum, args, &err_code))
876 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882
883 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
884 if (res) {
885 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
886 file, linenum, *res, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890
891 if (idle > 65535) {
892 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
896 global.tune.idle_timer = idle;
897 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100898 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200899 if (alertif_too_many_args(1, file, linenum, args, &err_code))
900 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100901 if (global.tune.client_rcvbuf != 0) {
902 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
903 err_code |= ERR_ALERT;
904 goto out;
905 }
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 global.tune.client_rcvbuf = atol(args[1]);
912 }
913 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200914 if (alertif_too_many_args(1, file, linenum, args, &err_code))
915 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100916 if (global.tune.server_rcvbuf != 0) {
917 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
918 err_code |= ERR_ALERT;
919 goto out;
920 }
921 if (*(args[1]) == 0) {
922 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926 global.tune.server_rcvbuf = atol(args[1]);
927 }
928 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200929 if (alertif_too_many_args(1, file, linenum, args, &err_code))
930 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100931 if (global.tune.client_sndbuf != 0) {
932 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT;
934 goto out;
935 }
936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto out;
940 }
941 global.tune.client_sndbuf = atol(args[1]);
942 }
943 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200944 if (alertif_too_many_args(1, file, linenum, args, &err_code))
945 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100946 if (global.tune.server_sndbuf != 0) {
947 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT;
949 goto out;
950 }
951 if (*(args[1]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
956 global.tune.server_sndbuf = atol(args[1]);
957 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200958 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200959 if (alertif_too_many_args(1, file, linenum, args, &err_code))
960 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200961 if (*(args[1]) == 0) {
962 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 global.tune.pipesize = atol(args[1]);
967 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100968 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200969 if (alertif_too_many_args(1, file, linenum, args, &err_code))
970 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100971 if (*(args[1]) == 0) {
972 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
973 err_code |= ERR_ALERT | ERR_FATAL;
974 goto out;
975 }
976 global.tune.cookie_len = atol(args[1]) + 1;
977 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200978 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200979 if (alertif_too_many_args(1, file, linenum, args, &err_code))
980 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200981 if (*(args[1]) == 0) {
982 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986 global.tune.max_http_hdr = atol(args[1]);
987 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100988 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
989#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200990 if (alertif_too_many_args(1, file, linenum, args, &err_code))
991 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100992 if (*args[1]) {
993 global.tune.zlibmemlevel = atoi(args[1]);
994 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
995 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
996 file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 } else {
1001 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1002 file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006#else
1007 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010#endif
1011 }
1012 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1013#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001014 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1015 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001016 if (*args[1]) {
1017 global.tune.zlibwindowsize = atoi(args[1]);
1018 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1019 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1020 file, linenum, args[0]);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023 }
1024 } else {
1025 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030#else
1031 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
1034#endif
1035 }
William Lallemandf3747832012-11-09 12:33:10 +01001036 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001037 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1038 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001039 if (*args[1]) {
1040 global.tune.comp_maxlevel = atoi(args[1]);
1041 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1042 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1043 file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047 } else {
1048 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1049 file, linenum, args[0]);
1050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
1052 }
1053 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001054 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1055 if (*args[1]) {
1056 global.tune.pattern_cache = atoi(args[1]);
1057 if (global.tune.pattern_cache < 0) {
1058 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1059 file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062 }
1063 } else {
1064 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1065 file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 else if (!strcmp(args[0], "uid")) {
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 (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001074 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001083 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1084 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]);
1085 err_code |= ERR_WARN;
1086 goto out;
1087 }
1088
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
1090 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001091 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001094 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
1098 if (*(args[1]) == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001103 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1104 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]);
1105 err_code |= ERR_WARN;
1106 goto out;
1107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 }
Simon Horman98637e52014-06-20 12:30:16 +09001109 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1111 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001112 global.external_check = 1;
1113 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001114 /* user/group name handling */
1115 else if (!strcmp(args[0], "user")) {
1116 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001119 if (global.uid != 0) {
1120 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001121 err_code |= ERR_ALERT;
1122 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001123 }
1124 errno = 0;
1125 ha_user = getpwnam(args[1]);
1126 if (ha_user != NULL) {
1127 global.uid = (int)ha_user->pw_uid;
1128 }
1129 else {
1130 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 +02001131 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001132 }
1133 }
1134 else if (!strcmp(args[0], "group")) {
1135 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001136 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1137 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001138 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001139 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT;
1141 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001142 }
1143 errno = 0;
1144 ha_group = getgrnam(args[1]);
1145 if (ha_group != NULL) {
1146 global.gid = (int)ha_group->gr_gid;
1147 }
1148 else {
1149 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 +02001150 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001151 }
1152 }
1153 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001155 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 if (*(args[1]) == 0) {
1158 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 }
1162 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001163 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1164 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1165 file, linenum, args[0], LONGBITS, global.nbproc);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
1168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 }
1170 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001171 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 if (global.maxconn != 0) {
1174 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001175 err_code |= ERR_ALERT;
1176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 }
1178 if (*(args[1]) == 0) {
1179 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 }
1183 global.maxconn = atol(args[1]);
1184#ifdef SYSTEM_MAXCONN
1185 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1186 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1187 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001188 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 }
1190#endif /* SYSTEM_MAXCONN */
1191 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001192 else if (!strcmp(args[0], "maxsslconn")) {
1193#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001194 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1195 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001196 if (*(args[1]) == 0) {
1197 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1198 err_code |= ERR_ALERT | ERR_FATAL;
1199 goto out;
1200 }
1201 global.maxsslconn = atol(args[1]);
1202#else
Emeric Brun0914df82012-10-02 18:45:42 +02001203 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001206#endif
1207 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001208 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1209#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001210 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1211 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001212 if (*(args[1]) == 0) {
1213 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
1216 }
1217 free(global.listen_default_ciphers);
1218 global.listen_default_ciphers = strdup(args[1]);
1219#else
1220 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223#endif
1224 }
1225 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1226#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001227 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1228 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234 free(global.connect_default_ciphers);
1235 global.connect_default_ciphers = strdup(args[1]);
1236#else
1237 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
1240#endif
1241 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001242#ifdef USE_OPENSSL
1243#ifndef OPENSSL_NO_DH
1244 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1245 if (*(args[1]) == 0) {
1246 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1251 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1252 err_code |= ERR_ALERT | ERR_FATAL;
1253 goto out;
1254 }
1255 }
1256#endif
1257#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001258 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001259 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1260 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001261 if (*(args[1]) == 0) {
1262 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
1265 }
1266 if (strcmp(args[1],"none") == 0)
1267 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1268 else if (strcmp(args[1],"required") == 0)
1269 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1270 else {
1271 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
1275 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001276 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001277 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1278 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001279 if (global.cps_lim != 0) {
1280 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1281 err_code |= ERR_ALERT;
1282 goto out;
1283 }
1284 if (*(args[1]) == 0) {
1285 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 global.cps_lim = atol(args[1]);
1290 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001291 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001292 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1293 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001294 if (global.sps_lim != 0) {
1295 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1296 err_code |= ERR_ALERT;
1297 goto out;
1298 }
1299 if (*(args[1]) == 0) {
1300 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
1304 global.sps_lim = atol(args[1]);
1305 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001306 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001307 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1308 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001309 if (global.ssl_lim != 0) {
1310 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT;
1312 goto out;
1313 }
1314 if (*(args[1]) == 0) {
1315 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
1318 }
1319 global.ssl_lim = atol(args[1]);
1320 }
William Lallemandd85f9172012-11-09 17:05:39 +01001321 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001322 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1323 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001324 if (*(args[1]) == 0) {
1325 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329 global.comp_rate_lim = atoi(args[1]) * 1024;
1330 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001331 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001332 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1333 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001334 if (global.maxpipes != 0) {
1335 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001336 err_code |= ERR_ALERT;
1337 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001338 }
1339 if (*(args[1]) == 0) {
1340 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001343 }
1344 global.maxpipes = atol(args[1]);
1345 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001346 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001347 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1348 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001349 if (*(args[1]) == 0) {
1350 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
William Lallemande3a7d992012-11-20 11:25:20 +01001354 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001355 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001356 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001357 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1358 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001359 if (*(args[1]) == 0) {
1360 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363 }
1364 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001365 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001366 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto out;
1369 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001370 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001371
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001373 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001375 if (global.rlimit_nofile != 0) {
1376 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001377 err_code |= ERR_ALERT;
1378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 }
1380 if (*(args[1]) == 0) {
1381 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
1383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
1385 global.rlimit_nofile = atol(args[1]);
1386 }
1387 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001388 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 if (global.chroot != NULL) {
1391 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 err_code |= ERR_ALERT;
1393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 }
1395 if (*(args[1]) == 0) {
1396 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 }
1400 global.chroot = strdup(args[1]);
1401 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001402 else if (!strcmp(args[0], "description")) {
1403 int i, len=0;
1404 char *d;
1405
1406 if (!*args[1]) {
1407 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1408 file, linenum, args[0]);
1409 err_code |= ERR_ALERT | ERR_FATAL;
1410 goto out;
1411 }
1412
Willy Tarreau348acfe2014-04-14 15:00:39 +02001413 for (i = 1; *args[i]; i++)
1414 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001415
1416 if (global.desc)
1417 free(global.desc);
1418
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001419 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001420
Willy Tarreau348acfe2014-04-14 15:00:39 +02001421 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1422 for (i = 2; *args[i]; i++)
1423 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001424 }
1425 else if (!strcmp(args[0], "node")) {
1426 int i;
1427 char c;
1428
William Lallemand1a748ae2015-05-19 16:37:23 +02001429 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1430 goto out;
1431
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001432 for (i=0; args[1][i]; i++) {
1433 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001434 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1435 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001436 break;
1437 }
1438
1439 if (!i || args[1][i]) {
1440 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1441 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1442 file, linenum, args[0]);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446
1447 if (global.node)
1448 free(global.node);
1449
1450 global.node = strdup(args[1]);
1451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001453 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 if (global.pidfile != NULL) {
1456 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001457 err_code |= ERR_ALERT;
1458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 }
1460 if (*(args[1]) == 0) {
1461 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
1463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 }
1465 global.pidfile = strdup(args[1]);
1466 }
Emeric Bruned760922010-10-22 17:59:25 +02001467 else if (!strcmp(args[0], "unix-bind")) {
1468 int cur_arg = 1;
1469 while (*(args[cur_arg])) {
1470 if (!strcmp(args[cur_arg], "prefix")) {
1471 if (global.unix_bind.prefix != NULL) {
1472 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1473 err_code |= ERR_ALERT;
1474 cur_arg += 2;
1475 continue;
1476 }
1477
1478 if (*(args[cur_arg+1]) == 0) {
1479 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto out;
1482 }
1483 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1484 cur_arg += 2;
1485 continue;
1486 }
1487
1488 if (!strcmp(args[cur_arg], "mode")) {
1489
1490 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1491 cur_arg += 2;
1492 continue;
1493 }
1494
1495 if (!strcmp(args[cur_arg], "uid")) {
1496
1497 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1498 cur_arg += 2;
1499 continue;
1500 }
1501
1502 if (!strcmp(args[cur_arg], "gid")) {
1503
1504 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1505 cur_arg += 2;
1506 continue;
1507 }
1508
1509 if (!strcmp(args[cur_arg], "user")) {
1510 struct passwd *user;
1511
1512 user = getpwnam(args[cur_arg + 1]);
1513 if (!user) {
1514 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1515 file, linenum, args[0], args[cur_arg + 1 ]);
1516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
1518 }
1519
1520 global.unix_bind.ux.uid = user->pw_uid;
1521 cur_arg += 2;
1522 continue;
1523 }
1524
1525 if (!strcmp(args[cur_arg], "group")) {
1526 struct group *group;
1527
1528 group = getgrnam(args[cur_arg + 1]);
1529 if (!group) {
1530 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1531 file, linenum, args[0], args[cur_arg + 1 ]);
1532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
1534 }
1535
1536 global.unix_bind.ux.gid = group->gr_gid;
1537 cur_arg += 2;
1538 continue;
1539 }
1540
Willy Tarreaub48f9582011-09-05 01:17:06 +02001541 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001542 file, linenum, args[0]);
1543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
1546 }
William Lallemand0f99e342011-10-12 17:50:54 +02001547 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1548 /* delete previous herited or defined syslog servers */
1549 struct logsrv *back;
1550 struct logsrv *tmp;
1551
1552 if (*(args[1]) != 0) {
1553 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
1557
1558 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1559 LIST_DEL(&tmp->list);
1560 free(tmp);
1561 }
1562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001564 struct sockaddr_storage *sk;
1565 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001566 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001567 int arg = 0;
1568 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001569
William Lallemand1a748ae2015-05-19 16:37:23 +02001570 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1571 goto out;
1572
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 if (*(args[1]) == 0 || *(args[2]) == 0) {
1574 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001575 err_code |= ERR_ALERT | ERR_FATAL;
1576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 }
William Lallemand0f99e342011-10-12 17:50:54 +02001578
Vincent Bernat02779b62016-04-03 13:48:43 +02001579 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001580
Willy Tarreau18324f52014-06-27 18:10:07 +02001581 /* just after the address, a length may be specified */
1582 if (strcmp(args[arg+2], "len") == 0) {
1583 len = atoi(args[arg+3]);
1584 if (len < 80 || len > 65535) {
1585 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1586 file, linenum, args[arg+3]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590 logsrv->maxlen = len;
1591
1592 /* skip these two args */
1593 arg += 2;
1594 }
1595 else
1596 logsrv->maxlen = MAX_SYSLOG_LEN;
1597
1598 if (logsrv->maxlen > global.max_syslog_len) {
1599 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001600 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1601 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1602 logline = my_realloc2(logline, global.max_syslog_len + 1);
1603 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001604 }
1605
Dragan Dosen1322d092015-09-22 16:05:32 +02001606 /* after the length, a format may be specified */
1607 if (strcmp(args[arg+2], "format") == 0) {
1608 logsrv->format = get_log_format(args[arg+3]);
1609 if (logsrv->format < 0) {
1610 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1611 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001612 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001613 goto out;
1614 }
1615
1616 /* skip these two args */
1617 arg += 2;
1618 }
1619
David Carlier97880bb2016-04-08 10:35:26 +01001620 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1621 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001622 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001623 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001624
Willy Tarreau18324f52014-06-27 18:10:07 +02001625 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001626 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001627 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001628 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001629 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 }
1631
William Lallemand0f99e342011-10-12 17:50:54 +02001632 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001633 if (*(args[arg+3])) {
1634 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001635 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001636 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001638 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
1640 }
1641
William Lallemand0f99e342011-10-12 17:50:54 +02001642 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001643 if (*(args[arg+4])) {
1644 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001645 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001646 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001647 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001648 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001649 }
1650 }
1651
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001652 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001653 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001654 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001655 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001656 free(logsrv);
1657 goto out;
1658 }
1659 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001660
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001661 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001662 if (port1 != port2) {
1663 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1664 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001665 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001666 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001667 goto out;
1668 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001669
William Lallemand0f99e342011-10-12 17:50:54 +02001670 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001671 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001672 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674
William Lallemand0f99e342011-10-12 17:50:54 +02001675 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001676 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001677 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1678 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001679
1680 if (global.log_send_hostname != NULL) {
1681 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1682 err_code |= ERR_ALERT;
1683 goto out;
1684 }
1685
1686 if (*(args[1]))
1687 name = args[1];
1688 else
1689 name = hostname;
1690
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001691 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001692 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001693 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001694 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1695 if (global.server_state_base != NULL) {
1696 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1697 err_code |= ERR_ALERT;
1698 goto out;
1699 }
1700
1701 if (!*(args[1])) {
1702 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1703 err_code |= ERR_FATAL;
1704 goto out;
1705 }
1706
1707 global.server_state_base = strdup(args[1]);
1708 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001709 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1710 if (global.server_state_file != NULL) {
1711 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1712 err_code |= ERR_ALERT;
1713 goto out;
1714 }
1715
1716 if (!*(args[1])) {
1717 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1718 err_code |= ERR_FATAL;
1719 goto out;
1720 }
1721
1722 global.server_state_file = strdup(args[1]);
1723 }
Kevinm48936af2010-12-22 16:08:21 +00001724 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001725 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1726 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001727 if (*(args[1]) == 0) {
1728 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
1731 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001732 chunk_destroy(&global.log_tag);
1733 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001734 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001735 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001736 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1737 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001738 if (global.spread_checks != 0) {
1739 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001740 err_code |= ERR_ALERT;
1741 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001742 }
1743 if (*(args[1]) == 0) {
1744 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001747 }
1748 global.spread_checks = atol(args[1]);
1749 if (global.spread_checks < 0 || global.spread_checks > 50) {
1750 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001751 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001754 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1755 const char *err;
1756 unsigned int val;
1757
William Lallemand1a748ae2015-05-19 16:37:23 +02001758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1759 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001760 if (*(args[1]) == 0) {
1761 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
1764 }
1765
1766 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1767 if (err) {
1768 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 }
1771 global.max_spread_checks = val;
1772 if (global.max_spread_checks < 0) {
1773 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1774 err_code |= ERR_ALERT | ERR_FATAL;
1775 }
1776 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001777 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1778#ifdef USE_CPU_AFFINITY
1779 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001780 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001781 unsigned long cpus = 0;
1782
1783 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001784 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001785 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001786 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001787 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001788 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001789 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001790 proc = atol(args[1]);
1791 if (proc >= 1 && proc <= LONGBITS)
1792 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001793 }
1794
1795 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001796 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",
1797 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800 }
1801
1802 cur_arg = 2;
1803 while (*args[cur_arg]) {
1804 unsigned int low, high;
1805
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001806 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001807 char *dash = strchr(args[cur_arg], '-');
1808
1809 low = high = str2uic(args[cur_arg]);
1810 if (dash)
1811 high = str2uic(dash + 1);
1812
1813 if (high < low) {
1814 unsigned int swap = low;
1815 low = high;
1816 high = swap;
1817 }
1818
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001819 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001820 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001821 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825
1826 while (low <= high)
1827 cpus |= 1UL << low++;
1828 }
1829 else {
1830 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1831 file, linenum, args[0], args[cur_arg]);
1832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835 cur_arg++;
1836 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001837 for (i = 0; i < LONGBITS; i++)
1838 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001839 global.cpu_map[i] = cpus;
1840#else
1841 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844#endif
1845 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001846 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1847 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1848 goto out;
1849
1850 if (*(args[2]) == 0) {
1851 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
1854 }
1855
1856 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1857 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1858 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862 }
1863 else if (!strcmp(args[0], "unsetenv")) {
1864 int arg;
1865
1866 if (*(args[1]) == 0) {
1867 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870 }
1871
1872 for (arg = 1; *args[arg]; arg++) {
1873 if (unsetenv(args[arg]) != 0) {
1874 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
1877 }
1878 }
1879 }
1880 else if (!strcmp(args[0], "resetenv")) {
1881 extern char **environ;
1882 char **env = environ;
1883
1884 /* args contain variable names to keep, one per argument */
1885 while (*env) {
1886 int arg;
1887
1888 /* look for current variable in among all those we want to keep */
1889 for (arg = 1; *args[arg]; arg++) {
1890 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1891 (*env)[strlen(args[arg])] == '=')
1892 break;
1893 }
1894
1895 /* delete this variable */
1896 if (!*args[arg]) {
1897 char *delim = strchr(*env, '=');
1898
1899 if (!delim || delim - *env >= trash.size) {
1900 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
1903 }
1904
1905 memcpy(trash.str, *env, delim - *env);
1906 trash.str[delim - *env] = 0;
1907
1908 if (unsetenv(trash.str) != 0) {
1909 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1910 err_code |= ERR_ALERT | ERR_FATAL;
1911 goto out;
1912 }
1913 }
1914 else
1915 env++;
1916 }
1917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001919 struct cfg_kw_list *kwl;
1920 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001921 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001922
1923 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1924 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1925 if (kwl->kw[index].section != CFG_GLOBAL)
1926 continue;
1927 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001928 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001929 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001930 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001932 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001933 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001934 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001935 err_code |= ERR_WARN;
1936 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001937 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001938 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001939 }
1940 }
1941 }
1942
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001944 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001946
Willy Tarreau058e9072009-07-20 09:30:05 +02001947 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001948 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001949 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950}
1951
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001952void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001954 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 defproxy.mode = PR_MODE_TCP;
1956 defproxy.state = PR_STNEW;
1957 defproxy.maxconn = cfg_maxpconn;
1958 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001959 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001960
Simon Horman66183002013-02-23 10:16:43 +09001961 defproxy.defsrv.check.inter = DEF_CHKINTR;
1962 defproxy.defsrv.check.fastinter = 0;
1963 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001964 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1965 defproxy.defsrv.agent.fastinter = 0;
1966 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001967 defproxy.defsrv.check.rise = DEF_RISETIME;
1968 defproxy.defsrv.check.fall = DEF_FALLTIME;
1969 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1970 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001971 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001972 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001973 defproxy.defsrv.maxqueue = 0;
1974 defproxy.defsrv.minconn = 0;
1975 defproxy.defsrv.maxconn = 0;
1976 defproxy.defsrv.slowstart = 0;
1977 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1978 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1979 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001980
1981 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001982 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983}
1984
Willy Tarreauade5ec42010-01-28 19:33:49 +01001985
Willy Tarreau63af98d2014-05-18 08:11:41 +02001986/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1987 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1988 * ERR_FATAL in case of error.
1989 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001990static int create_cond_regex_rule(const char *file, int line,
1991 struct proxy *px, int dir, int action, int flags,
1992 const char *cmd, const char *reg, const char *repl,
1993 const char **cond_start)
1994{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001995 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001996 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001997 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001998 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001999 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002000 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002001 int cs;
2002 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002003
2004 if (px == &defproxy) {
2005 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002006 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002007 goto err;
2008 }
2009
2010 if (*reg == 0) {
2011 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002012 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002013 goto err;
2014 }
2015
2016 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002017 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002018
Willy Tarreau5321c422010-01-28 20:35:13 +01002019 if (cond_start &&
2020 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002021 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2022 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2023 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002024 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002025 goto err;
2026 }
2027 }
2028 else if (cond_start && **cond_start) {
2029 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2030 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002031 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002032 goto err;
2033 }
2034
Willy Tarreau63af98d2014-05-18 08:11:41 +02002035 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002036 (dir == SMP_OPT_DIR_REQ) ?
2037 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2038 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2039 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002040
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002041 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002042 if (!preg) {
2043 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002044 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002045 goto err;
2046 }
2047
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002048 cs = !(flags & REG_ICASE);
2049 cap = !(flags & REG_NOSUB);
2050 error = NULL;
2051 if (!regex_comp(reg, preg, cs, cap, &error)) {
2052 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2053 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002054 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002055 goto err;
2056 }
2057
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002058 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002059 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002060 if (repl && err) {
2061 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2062 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002063 ret_code |= ERR_ALERT | ERR_FATAL;
2064 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002065 }
2066
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002067 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002068 ret_code |= ERR_WARN;
2069
2070 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002071
Willy Tarreau63af98d2014-05-18 08:11:41 +02002072 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002073 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002074 err:
2075 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002076 free(errmsg);
2077 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002078}
2079
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080/*
William Lallemand51097192015-04-14 16:35:22 +02002081 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002082 * Returns the error code, 0 if OK, or any combination of :
2083 * - ERR_ABORT: must abort ASAP
2084 * - ERR_FATAL: we can continue parsing but not start the service
2085 * - ERR_WARN: a warning has been emitted
2086 * - ERR_ALERT: an alert has been emitted
2087 * Only the two first ones can stop processing, the two others are just
2088 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002090int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2091{
2092 static struct peers *curpeers = NULL;
2093 struct peer *newpeer = NULL;
2094 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002095 struct bind_conf *bind_conf;
2096 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002098 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002099
2100 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002101 if (!*args[1]) {
2102 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002103 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002104 goto out;
2105 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002106
William Lallemand6e62fb62015-04-28 16:55:23 +02002107 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2108 goto out;
2109
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 err = invalid_char(args[1]);
2111 if (err) {
2112 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2113 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002114 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002115 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002116 }
2117
2118 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2119 /*
2120 * If there are two proxies with the same name only following
2121 * combinations are allowed:
2122 */
2123 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002124 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 +02002125 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002127 }
2128 }
2129
Vincent Bernat02779b62016-04-03 13:48:43 +02002130 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2132 err_code |= ERR_ALERT | ERR_ABORT;
2133 goto out;
2134 }
2135
2136 curpeers->next = peers;
2137 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002138 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002139 curpeers->conf.line = linenum;
2140 curpeers->last_change = now.tv_sec;
2141 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002142 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002143 }
2144 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002145 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002146 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002147 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002148
2149 if (!*args[2]) {
2150 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2151 file, linenum, args[0]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
2156 err = invalid_char(args[1]);
2157 if (err) {
2158 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2159 file, linenum, *err, args[1]);
2160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
2162 }
2163
Vincent Bernat02779b62016-04-03 13:48:43 +02002164 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002165 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2166 err_code |= ERR_ALERT | ERR_ABORT;
2167 goto out;
2168 }
2169
2170 /* the peers are linked backwards first */
2171 curpeers->count++;
2172 newpeer->next = curpeers->remote;
2173 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002174 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002175 newpeer->conf.line = linenum;
2176
2177 newpeer->last_change = now.tv_sec;
2178 newpeer->id = strdup(args[1]);
2179
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002180 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002181 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002182 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002185 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002186
2187 proto = protocol_by_family(sk->ss_family);
2188 if (!proto || !proto->connect) {
2189 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2190 file, linenum, args[0], args[1]);
2191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
2193 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002194
2195 if (port1 != port2) {
2196 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2197 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
2200 }
2201
Willy Tarreau2aa38802013-02-20 19:20:59 +01002202 if (!port1) {
2203 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2204 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002208
Emeric Brun32da3c42010-09-23 18:39:19 +02002209 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002210 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002211 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002212 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002213
Emeric Brun32da3c42010-09-23 18:39:19 +02002214 if (strcmp(newpeer->id, localpeer) == 0) {
2215 /* Current is local peer, it define a frontend */
2216 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002217 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002218
2219 if (!curpeers->peers_fe) {
2220 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2221 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2222 err_code |= ERR_ALERT | ERR_ABORT;
2223 goto out;
2224 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002225
Willy Tarreau237250c2011-07-29 01:49:03 +02002226 init_new_proxy(curpeers->peers_fe);
2227 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002228 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002229 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2230 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002231 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002232
2233 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2234
Willy Tarreau902636f2013-03-10 19:44:48 +01002235 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2236 if (errmsg && *errmsg) {
2237 indent_msg(&errmsg, 2);
2238 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002239 }
2240 else
2241 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2242 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002243 err_code |= ERR_FATAL;
2244 goto out;
2245 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002246
2247 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002248 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002249 l->maxconn = curpeers->peers_fe->maxconn;
2250 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002251 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002252 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002253 l->analysers |= curpeers->peers_fe->fe_req_ana;
2254 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002255 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2256 global.maxsock += l->maxconn;
2257 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002258 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002259 else {
2260 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2261 file, linenum, args[0], args[1],
2262 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2263 err_code |= ERR_FATAL;
2264 goto out;
2265 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002266 }
2267 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002268 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2269 curpeers->state = PR_STSTOPPED;
2270 }
2271 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2272 curpeers->state = PR_STNEW;
2273 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002274 else if (*args[0] != 0) {
2275 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2276 err_code |= ERR_ALERT | ERR_FATAL;
2277 goto out;
2278 }
2279
2280out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002281 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002282 return err_code;
2283}
2284
Baptiste Assmann325137d2015-04-13 23:40:55 +02002285/*
2286 * Parse a <resolvers> section.
2287 * Returns the error code, 0 if OK, or any combination of :
2288 * - ERR_ABORT: must abort ASAP
2289 * - ERR_FATAL: we can continue parsing but not start the service
2290 * - ERR_WARN: a warning has been emitted
2291 * - ERR_ALERT: an alert has been emitted
2292 * Only the two first ones can stop processing, the two others are just
2293 * indicators.
2294 */
2295int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2296{
2297 static struct dns_resolvers *curr_resolvers = NULL;
2298 struct dns_nameserver *newnameserver = NULL;
2299 const char *err;
2300 int err_code = 0;
2301 char *errmsg = NULL;
2302
2303 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2304 if (!*args[1]) {
2305 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2306 err_code |= ERR_ALERT | ERR_ABORT;
2307 goto out;
2308 }
2309
2310 err = invalid_char(args[1]);
2311 if (err) {
2312 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2313 file, linenum, *err, args[0], args[1]);
2314 err_code |= ERR_ALERT | ERR_ABORT;
2315 goto out;
2316 }
2317
2318 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2319 /* Error if two resolvers owns the same name */
2320 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2321 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2322 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2323 err_code |= ERR_ALERT | ERR_ABORT;
2324 }
2325 }
2326
Vincent Bernat02779b62016-04-03 13:48:43 +02002327 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002328 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2329 err_code |= ERR_ALERT | ERR_ABORT;
2330 goto out;
2331 }
2332
2333 /* default values */
2334 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2335 curr_resolvers->conf.file = strdup(file);
2336 curr_resolvers->conf.line = linenum;
2337 curr_resolvers->id = strdup(args[1]);
2338 curr_resolvers->query_ids = EB_ROOT;
2339 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002340 curr_resolvers->hold.valid = 10000;
2341 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002342 curr_resolvers->resolve_retries = 3;
2343 LIST_INIT(&curr_resolvers->nameserver_list);
2344 LIST_INIT(&curr_resolvers->curr_resolution);
2345 }
2346 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2347 struct sockaddr_storage *sk;
2348 int port1, port2;
2349 struct protocol *proto;
2350
2351 if (!*args[2]) {
2352 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2353 file, linenum, args[0]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357
2358 err = invalid_char(args[1]);
2359 if (err) {
2360 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2361 file, linenum, *err, args[1]);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365
Baptiste Assmanna315c552015-11-02 22:55:49 +01002366 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2367 /* Error if two resolvers owns the same name */
2368 if (strcmp(newnameserver->id, args[1]) == 0) {
2369 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2370 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2371 err_code |= ERR_ALERT | ERR_FATAL;
2372 }
2373 }
2374
Vincent Bernat02779b62016-04-03 13:48:43 +02002375 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002376 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2377 err_code |= ERR_ALERT | ERR_ABORT;
2378 goto out;
2379 }
2380
2381 /* the nameservers are linked backward first */
2382 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2383 curr_resolvers->count_nameservers++;
2384 newnameserver->resolvers = curr_resolvers;
2385 newnameserver->conf.file = strdup(file);
2386 newnameserver->conf.line = linenum;
2387 newnameserver->id = strdup(args[1]);
2388
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002389 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002390 if (!sk) {
2391 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
2394 }
2395
2396 proto = protocol_by_family(sk->ss_family);
2397 if (!proto || !proto->connect) {
2398 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2399 file, linenum, args[0], args[1]);
2400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
2402 }
2403
2404 if (port1 != port2) {
2405 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2406 file, linenum, args[0], args[1], args[2]);
2407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
2409 }
2410
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002411 if (!port1 && !port2) {
2412 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2413 file, linenum, args[0], args[1]);
2414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
2416 }
2417
Baptiste Assmann325137d2015-04-13 23:40:55 +02002418 newnameserver->addr = *sk;
2419 }
2420 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2421 const char *res;
2422 unsigned int time;
2423
2424 if (!*args[2]) {
2425 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2426 file, linenum, args[0]);
2427 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2432 if (res) {
2433 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2434 file, linenum, *res, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 if (strcmp(args[1], "valid") == 0)
2439 curr_resolvers->hold.valid = time;
2440 else {
2441 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2442 file, linenum, args[0], args[1]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446
2447 }
2448 else if (strcmp(args[0], "resolve_retries") == 0) {
2449 if (!*args[1]) {
2450 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2451 file, linenum, args[0]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455 curr_resolvers->resolve_retries = atoi(args[1]);
2456 }
2457 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002458 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002459 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2460 file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002464 else if (strcmp(args[1], "retry") == 0) {
2465 const char *res;
2466 unsigned int timeout_retry;
2467
2468 if (!*args[2]) {
2469 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2470 file, linenum, args[0], args[1]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
2474 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2475 if (res) {
2476 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2477 file, linenum, *res, args[0], args[1]);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481 curr_resolvers->timeout.retry = timeout_retry;
2482 }
2483 else {
2484 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2485 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
2488 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002489 } /* neither "nameserver" nor "resolvers" */
2490 else if (*args[0] != 0) {
2491 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495
2496 out:
2497 free(errmsg);
2498 return err_code;
2499}
Simon Horman0d16a402015-01-30 11:22:58 +09002500
2501/*
William Lallemand51097192015-04-14 16:35:22 +02002502 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002503 * Returns the error code, 0 if OK, or any combination of :
2504 * - ERR_ABORT: must abort ASAP
2505 * - ERR_FATAL: we can continue parsing but not start the service
2506 * - ERR_WARN: a warning has been emitted
2507 * - ERR_ALERT: an alert has been emitted
2508 * Only the two first ones can stop processing, the two others are just
2509 * indicators.
2510 */
2511int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2512{
2513 static struct mailers *curmailers = NULL;
2514 struct mailer *newmailer = NULL;
2515 const char *err;
2516 int err_code = 0;
2517 char *errmsg = NULL;
2518
2519 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2520 if (!*args[1]) {
2521 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2522 err_code |= ERR_ALERT | ERR_ABORT;
2523 goto out;
2524 }
2525
2526 err = invalid_char(args[1]);
2527 if (err) {
2528 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2529 file, linenum, *err, args[0], args[1]);
2530 err_code |= ERR_ALERT | ERR_ABORT;
2531 goto out;
2532 }
2533
2534 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2535 /*
2536 * If there are two proxies with the same name only following
2537 * combinations are allowed:
2538 */
2539 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002540 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 +09002541 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002543 }
2544 }
2545
Vincent Bernat02779b62016-04-03 13:48:43 +02002546 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002547 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2548 err_code |= ERR_ALERT | ERR_ABORT;
2549 goto out;
2550 }
2551
2552 curmailers->next = mailers;
2553 mailers = curmailers;
2554 curmailers->conf.file = strdup(file);
2555 curmailers->conf.line = linenum;
2556 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002557 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2558 * But need enough time so that timeouts don't occur
2559 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002560 }
2561 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2562 struct sockaddr_storage *sk;
2563 int port1, port2;
2564 struct protocol *proto;
2565
2566 if (!*args[2]) {
2567 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2568 file, linenum, args[0]);
2569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
2571 }
2572
2573 err = invalid_char(args[1]);
2574 if (err) {
2575 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2576 file, linenum, *err, args[1]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
2580
Vincent Bernat02779b62016-04-03 13:48:43 +02002581 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002582 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2583 err_code |= ERR_ALERT | ERR_ABORT;
2584 goto out;
2585 }
2586
2587 /* the mailers are linked backwards first */
2588 curmailers->count++;
2589 newmailer->next = curmailers->mailer_list;
2590 curmailers->mailer_list = newmailer;
2591 newmailer->mailers = curmailers;
2592 newmailer->conf.file = strdup(file);
2593 newmailer->conf.line = linenum;
2594
2595 newmailer->id = strdup(args[1]);
2596
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002597 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002598 if (!sk) {
2599 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
2603
2604 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002605 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2606 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002607 file, linenum, args[0], args[1]);
2608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
2610 }
2611
2612 if (port1 != port2) {
2613 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2614 file, linenum, args[0], args[1], args[2]);
2615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
2617 }
2618
2619 if (!port1) {
2620 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2621 file, linenum, args[0], args[1], args[2]);
2622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
2624 }
2625
2626 newmailer->addr = *sk;
2627 newmailer->proto = proto;
2628 newmailer->xprt = &raw_sock;
2629 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002630 }
2631 else if (strcmp(args[0], "timeout") == 0) {
2632 if (!*args[1]) {
2633 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2634 file, linenum, args[0]);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637 }
2638 else if (strcmp(args[1], "mail") == 0) {
2639 const char *res;
2640 unsigned int timeout_mail;
2641 if (!*args[2]) {
2642 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2643 file, linenum, args[0], args[1]);
2644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
2646 }
2647 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2648 if (res) {
2649 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2650 file, linenum, *res, args[0]);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
2653 }
2654 if (timeout_mail <= 0) {
2655 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
2658 }
2659 curmailers->timeout.mail = timeout_mail;
2660 } else {
2661 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2662 file, linenum, args[0], args[1]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666 }
Simon Horman0d16a402015-01-30 11:22:58 +09002667 else if (*args[0] != 0) {
2668 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
2671 }
2672
2673out:
2674 free(errmsg);
2675 return err_code;
2676}
2677
Simon Horman9dc49962015-01-30 11:22:59 +09002678static void free_email_alert(struct proxy *p)
2679{
2680 free(p->email_alert.mailers.name);
2681 p->email_alert.mailers.name = NULL;
2682 free(p->email_alert.from);
2683 p->email_alert.from = NULL;
2684 free(p->email_alert.to);
2685 p->email_alert.to = NULL;
2686 free(p->email_alert.myhostname);
2687 p->email_alert.myhostname = NULL;
2688}
2689
Willy Tarreau3842f002009-06-14 11:39:52 +02002690int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691{
2692 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002693 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002694 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002695 int rc;
2696 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002697 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002698 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002699 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002700 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002701 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702
Willy Tarreau977b8e42006-12-29 14:19:17 +01002703 if (!strcmp(args[0], "listen"))
2704 rc = PR_CAP_LISTEN;
2705 else if (!strcmp(args[0], "frontend"))
2706 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002707 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002708 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002709 else
2710 rc = PR_CAP_NONE;
2711
2712 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 if (!*args[1]) {
2714 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2715 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2716 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_ALERT | ERR_ABORT;
2718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002720
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002721 err = invalid_char(args[1]);
2722 if (err) {
2723 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2724 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002726 }
2727
Willy Tarreau8f50b682015-05-26 11:45:02 +02002728 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2729 if (curproxy) {
2730 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2731 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2732 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002733 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002734 }
2735
Vincent Bernat02779b62016-04-03 13:48:43 +02002736 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002738 err_code |= ERR_ALERT | ERR_ABORT;
2739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002741
Willy Tarreau97cb7802010-01-03 20:23:58 +01002742 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 curproxy->next = proxy;
2744 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002745 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2746 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002747 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002750 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751
William Lallemand6e62fb62015-04-28 16:55:23 +02002752 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2753 if (curproxy->cap & PR_CAP_FE)
2754 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
2757
2758 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002759 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002760 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002761
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002764 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002765 curproxy->no_options = defproxy.no_options;
2766 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002767 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002768 curproxy->except_net = defproxy.except_net;
2769 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002770 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002771 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002773 if (defproxy.fwdfor_hdr_len) {
2774 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2775 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2776 }
2777
Willy Tarreaub86db342009-11-30 11:50:16 +01002778 if (defproxy.orgto_hdr_len) {
2779 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2780 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2781 }
2782
Mark Lamourinec2247f02012-01-04 13:02:01 -05002783 if (defproxy.server_id_hdr_len) {
2784 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2785 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2786 }
2787
Willy Tarreau977b8e42006-12-29 14:19:17 +01002788 if (curproxy->cap & PR_CAP_FE) {
2789 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002790 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002791 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002792
2793 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002794 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2795 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002796
2797 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799
Willy Tarreau977b8e42006-12-29 14:19:17 +01002800 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002801 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002802 curproxy->fullconn = defproxy.fullconn;
2803 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002804 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002805 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002807 if (defproxy.check_req) {
2808 curproxy->check_req = calloc(1, defproxy.check_len);
2809 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002811 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002812
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002813 if (defproxy.expect_str) {
2814 curproxy->expect_str = strdup(defproxy.expect_str);
2815 if (defproxy.expect_regex) {
2816 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002817 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2818 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002819 }
2820 }
2821
Willy Tarreau67402132012-05-31 20:40:20 +02002822 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002823 if (defproxy.cookie_name)
2824 curproxy->cookie_name = strdup(defproxy.cookie_name);
2825 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002826 if (defproxy.cookie_domain)
2827 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002828
Willy Tarreau31936852010-10-06 16:59:56 +02002829 if (defproxy.cookie_maxidle)
2830 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2831
2832 if (defproxy.cookie_maxlife)
2833 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2834
Emeric Brun647caf12009-06-30 17:57:00 +02002835 if (defproxy.rdp_cookie_name)
2836 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2837 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2838
Willy Tarreau01732802007-11-01 22:48:15 +01002839 if (defproxy.url_param_name)
2840 curproxy->url_param_name = strdup(defproxy.url_param_name);
2841 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002842
Benoitaffb4812009-03-25 13:02:10 +01002843 if (defproxy.hh_name)
2844 curproxy->hh_name = strdup(defproxy.hh_name);
2845 curproxy->hh_len = defproxy.hh_len;
2846 curproxy->hh_match_domain = defproxy.hh_match_domain;
2847
Willy Tarreauef9a3602012-12-08 22:29:20 +01002848 if (defproxy.conn_src.iface_name)
2849 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2850 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002851 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002852#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002853 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002854#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002855 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002858 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859 if (defproxy.capture_name)
2860 curproxy->capture_name = strdup(defproxy.capture_name);
2861 curproxy->capture_namelen = defproxy.capture_namelen;
2862 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002866 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002867 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002868 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002869 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002870 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002871 curproxy->mon_net = defproxy.mon_net;
2872 curproxy->mon_mask = defproxy.mon_mask;
2873 if (defproxy.monitor_uri)
2874 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2875 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002876 if (defproxy.defbe.name)
2877 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002878
2879 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002880 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2881 if (curproxy->conf.logformat_string &&
2882 curproxy->conf.logformat_string != default_http_log_format &&
2883 curproxy->conf.logformat_string != default_tcp_log_format &&
2884 curproxy->conf.logformat_string != clf_http_log_format)
2885 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2886
2887 if (defproxy.conf.lfs_file) {
2888 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2889 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2890 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002891
2892 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2893 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2894 if (curproxy->conf.logformat_sd_string &&
2895 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2896 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2897
2898 if (defproxy.conf.lfsd_file) {
2899 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2900 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2901 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902 }
2903
2904 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002905 curproxy->timeout.connect = defproxy.timeout.connect;
2906 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002907 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002908 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002909 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002910 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002911 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002912 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002913 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002914 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002915 }
2916
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002918 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002919
2920 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002921 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002922 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002923 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002924 LIST_INIT(&node->list);
2925 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2926 }
2927
Willy Tarreau62a61232013-04-12 18:13:46 +02002928 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2929 if (curproxy->conf.uniqueid_format_string)
2930 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2931
Dragan Dosen43885c72015-10-01 13:18:13 +02002932 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002933
Willy Tarreau62a61232013-04-12 18:13:46 +02002934 if (defproxy.conf.uif_file) {
2935 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2936 curproxy->conf.uif_line = defproxy.conf.uif_line;
2937 }
William Lallemanda73203e2012-03-12 12:48:57 +01002938
2939 /* copy default header unique id */
2940 if (defproxy.header_unique_id)
2941 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2942
William Lallemand82fe75c2012-10-23 10:25:10 +02002943 /* default compression options */
2944 if (defproxy.comp != NULL) {
2945 curproxy->comp = calloc(1, sizeof(struct comp));
2946 curproxy->comp->algos = defproxy.comp->algos;
2947 curproxy->comp->types = defproxy.comp->types;
2948 }
2949
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002951 curproxy->conf.used_listener_id = EB_ROOT;
2952 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002953
Simon Horman98637e52014-06-20 12:30:16 +09002954 if (defproxy.check_path)
2955 curproxy->check_path = strdup(defproxy.check_path);
2956 if (defproxy.check_command)
2957 curproxy->check_command = strdup(defproxy.check_command);
2958
Simon Horman9dc49962015-01-30 11:22:59 +09002959 if (defproxy.email_alert.mailers.name)
2960 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2961 if (defproxy.email_alert.from)
2962 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2963 if (defproxy.email_alert.to)
2964 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2965 if (defproxy.email_alert.myhostname)
2966 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002967 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002968 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002969
Willy Tarreau93893792009-07-23 13:19:11 +02002970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 }
2972 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2973 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002974 /* FIXME-20070101: we should do this too at the end of the
2975 * config parsing to free all default values.
2976 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002977 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2978 err_code |= ERR_ABORT;
2979 goto out;
2980 }
2981
Willy Tarreaua534fea2008-08-03 12:19:50 +02002982 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002983 free(defproxy.check_command);
2984 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002985 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002986 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002987 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002988 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002989 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002990 free(defproxy.capture_name);
2991 free(defproxy.monitor_uri);
2992 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002993 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002994 free(defproxy.fwdfor_hdr_name);
2995 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002996 free(defproxy.orgto_hdr_name);
2997 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002998 free(defproxy.server_id_hdr_name);
2999 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003000 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003001 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003002 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003003 free(defproxy.expect_regex);
3004 defproxy.expect_regex = NULL;
3005 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003006
Willy Tarreau62a61232013-04-12 18:13:46 +02003007 if (defproxy.conf.logformat_string != default_http_log_format &&
3008 defproxy.conf.logformat_string != default_tcp_log_format &&
3009 defproxy.conf.logformat_string != clf_http_log_format)
3010 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003011
Willy Tarreau62a61232013-04-12 18:13:46 +02003012 free(defproxy.conf.uniqueid_format_string);
3013 free(defproxy.conf.lfs_file);
3014 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003015 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003016 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003017
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003018 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3019 free(defproxy.conf.logformat_sd_string);
3020 free(defproxy.conf.lfsd_file);
3021
Willy Tarreaua534fea2008-08-03 12:19:50 +02003022 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003023 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003024
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 /* we cannot free uri_auth because it might already be used */
3026 init_default_instance();
3027 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003028 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3029 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003030 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
3033 else if (curproxy == NULL) {
3034 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003038
3039 /* update the current file and line being parsed */
3040 curproxy->conf.args.file = curproxy->conf.file;
3041 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003042
3043 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003044 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3045 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3046 if (err_code & ERR_FATAL)
3047 goto out;
3048 }
3049 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003050 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003051 int cur_arg;
3052
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 if (curproxy == &defproxy) {
3054 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003058 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060
Willy Tarreau24709282013-03-10 21:32:12 +01003061 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003062 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003067
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003068 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003069
3070 /* use default settings for unix sockets */
3071 bind_conf->ux.uid = global.unix_bind.ux.uid;
3072 bind_conf->ux.gid = global.unix_bind.ux.gid;
3073 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003074
3075 /* NOTE: the following line might create several listeners if there
3076 * are comma-separated IPs or port ranges. So all further processing
3077 * will have to be applied to all listeners created after last_listen.
3078 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003079 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3080 if (errmsg && *errmsg) {
3081 indent_msg(&errmsg, 2);
3082 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003083 }
3084 else
3085 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3086 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_FATAL;
3088 goto out;
3089 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003090
Willy Tarreau4348fad2012-09-20 16:48:07 +02003091 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3092 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003093 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003094 }
3095
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003096 cur_arg = 2;
3097 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003098 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003099 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003100 char *err;
3101
Willy Tarreau26982662012-09-12 23:17:10 +02003102 kw = bind_find_kw(args[cur_arg]);
3103 if (kw) {
3104 char *err = NULL;
3105 int code;
3106
3107 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003108 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3109 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003110 cur_arg += 1 + kw->skip ;
3111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
3113 }
3114
Willy Tarreau4348fad2012-09-20 16:48:07 +02003115 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003116 err_code |= code;
3117
3118 if (code) {
3119 if (err && *err) {
3120 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003121 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003122 }
3123 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003124 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3125 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003126 if (code & ERR_FATAL) {
3127 free(err);
3128 cur_arg += 1 + kw->skip;
3129 goto out;
3130 }
3131 }
3132 free(err);
3133 cur_arg += 1 + kw->skip;
3134 continue;
3135 }
3136
Willy Tarreau8638f482012-09-18 18:01:17 +02003137 err = NULL;
3138 if (!bind_dumped) {
3139 bind_dump_kws(&err);
3140 indent_msg(&err, 4);
3141 bind_dumped = 1;
3142 }
3143
3144 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3145 file, linenum, args[0], args[1], args[cur_arg],
3146 err ? " Registered keywords :" : "", err ? err : "");
3147 free(err);
3148
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003151 }
Willy Tarreau93893792009-07-23 13:19:11 +02003152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
3154 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003155 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3157 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003161 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003163
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 /* flush useless bits */
3165 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003168 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003169 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003171
William Lallemanddf1425a2015-04-28 20:17:49 +02003172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3173 goto out;
3174
Willy Tarreau1c47f852006-07-09 08:22:27 +02003175 if (!*args[1]) {
3176 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3177 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003180 }
3181
Willy Tarreaua534fea2008-08-03 12:19:50 +02003182 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003183 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003184 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003185 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003186 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3187
Willy Tarreau93893792009-07-23 13:19:11 +02003188 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003191 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3192 goto out;
3193
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3195 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3196 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3197 else {
3198 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003203 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003204 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003205
3206 if (curproxy == &defproxy) {
3207 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3208 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003211 }
3212
William Lallemanddf1425a2015-04-28 20:17:49 +02003213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3214 goto out;
3215
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003216 if (!*args[1]) {
3217 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3218 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003221 }
3222
3223 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003224 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003225 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003226
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003227 if (curproxy->uuid <= 0) {
3228 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003229 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003232 }
3233
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003234 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3235 if (node) {
3236 struct proxy *target = container_of(node, struct proxy, conf.id);
3237 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3238 file, linenum, proxy_type_str(curproxy), curproxy->id,
3239 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
3242 }
3243 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003244 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003245 else if (!strcmp(args[0], "description")) {
3246 int i, len=0;
3247 char *d;
3248
Cyril Bonté99ed3272010-01-24 23:29:44 +01003249 if (curproxy == &defproxy) {
3250 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3251 file, linenum, args[0]);
3252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
3254 }
3255
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003256 if (!*args[1]) {
3257 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3258 file, linenum, args[0]);
3259 return -1;
3260 }
3261
Willy Tarreau348acfe2014-04-14 15:00:39 +02003262 for (i = 1; *args[i]; i++)
3263 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003264
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003265 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003266 curproxy->desc = d;
3267
Willy Tarreau348acfe2014-04-14 15:00:39 +02003268 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3269 for (i = 2; *args[i]; i++)
3270 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003271
3272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003274 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 curproxy->state = PR_STSTOPPED;
3277 }
3278 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003279 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 curproxy->state = PR_STNEW;
3282 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003283 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3284 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003285 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003286
3287 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003288 unsigned int low, high;
3289
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003290 if (strcmp(args[cur_arg], "all") == 0) {
3291 set = 0;
3292 break;
3293 }
3294 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003295 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003296 }
3297 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003298 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003299 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003300 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003301 char *dash = strchr(args[cur_arg], '-');
3302
3303 low = high = str2uic(args[cur_arg]);
3304 if (dash)
3305 high = str2uic(dash + 1);
3306
3307 if (high < low) {
3308 unsigned int swap = low;
3309 low = high;
3310 high = swap;
3311 }
3312
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003313 if (low < 1 || high > LONGBITS) {
3314 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3315 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003318 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003319 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003320 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003321 }
3322 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003323 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3324 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003327 }
3328 cur_arg++;
3329 }
3330 curproxy->bind_proc = set;
3331 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003332 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003333 if (curproxy == &defproxy) {
3334 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003337 }
3338
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003339 err = invalid_char(args[1]);
3340 if (err) {
3341 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3342 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003344 }
3345
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003346 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003347 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3348 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003351 }
3352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3354 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355
Willy Tarreau977b8e42006-12-29 14:19:17 +01003356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003358
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 if (*(args[1]) == 0) {
3360 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3361 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003365
Willy Tarreau67402132012-05-31 20:40:20 +02003366 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003367 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003368 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003369 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 curproxy->cookie_name = strdup(args[1]);
3371 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003372
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 cur_arg = 2;
3374 while (*(args[cur_arg])) {
3375 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003376 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 }
3378 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003379 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 }
3381 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003382 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 }
3384 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003385 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
3387 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003388 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003390 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003391 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003394 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003396 else if (!strcmp(args[cur_arg], "httponly")) {
3397 curproxy->ck_opts |= PR_CK_HTTPONLY;
3398 }
3399 else if (!strcmp(args[cur_arg], "secure")) {
3400 curproxy->ck_opts |= PR_CK_SECURE;
3401 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003402 else if (!strcmp(args[cur_arg], "domain")) {
3403 if (!*args[cur_arg + 1]) {
3404 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3405 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003408 }
3409
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003410 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003411 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003412 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3413 " dots nor does not start with a dot."
3414 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003415 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003416 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003417 }
3418
3419 err = invalid_domainchar(args[cur_arg + 1]);
3420 if (err) {
3421 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3422 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003425 }
3426
Willy Tarreau68a897b2009-12-03 23:28:34 +01003427 if (!curproxy->cookie_domain) {
3428 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3429 } else {
3430 /* one domain was already specified, add another one by
3431 * building the string which will be returned along with
3432 * the cookie.
3433 */
3434 char *new_ptr;
3435 int new_len = strlen(curproxy->cookie_domain) +
3436 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3437 new_ptr = malloc(new_len);
3438 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3439 free(curproxy->cookie_domain);
3440 curproxy->cookie_domain = new_ptr;
3441 }
Willy Tarreau31936852010-10-06 16:59:56 +02003442 cur_arg++;
3443 }
3444 else if (!strcmp(args[cur_arg], "maxidle")) {
3445 unsigned int maxidle;
3446 const char *res;
3447
3448 if (!*args[cur_arg + 1]) {
3449 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3450 file, linenum, args[cur_arg]);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454
3455 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3456 if (res) {
3457 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3458 file, linenum, *res, args[cur_arg]);
3459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
3462 curproxy->cookie_maxidle = maxidle;
3463 cur_arg++;
3464 }
3465 else if (!strcmp(args[cur_arg], "maxlife")) {
3466 unsigned int maxlife;
3467 const char *res;
3468
3469 if (!*args[cur_arg + 1]) {
3470 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3471 file, linenum, args[cur_arg]);
3472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
3475
3476 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3477 if (res) {
3478 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3479 file, linenum, *res, args[cur_arg]);
3480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
3482 }
3483 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003484 cur_arg++;
3485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003487 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 +02003488 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 }
3492 cur_arg++;
3493 }
Willy Tarreau67402132012-05-31 20:40:20 +02003494 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3496 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 }
3499
Willy Tarreau67402132012-05-31 20:40:20 +02003500 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003501 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3502 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003505
Willy Tarreau67402132012-05-31 20:40:20 +02003506 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003507 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3508 file, linenum);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003512 else if (!strcmp(args[0], "email-alert")) {
3513 if (*(args[1]) == 0) {
3514 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3515 file, linenum, args[0]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519
3520 if (!strcmp(args[1], "from")) {
3521 if (*(args[1]) == 0) {
3522 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3523 file, linenum, args[1]);
3524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
3526 }
3527 free(curproxy->email_alert.from);
3528 curproxy->email_alert.from = strdup(args[2]);
3529 }
3530 else if (!strcmp(args[1], "mailers")) {
3531 if (*(args[1]) == 0) {
3532 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3533 file, linenum, args[1]);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
3537 free(curproxy->email_alert.mailers.name);
3538 curproxy->email_alert.mailers.name = strdup(args[2]);
3539 }
3540 else if (!strcmp(args[1], "myhostname")) {
3541 if (*(args[1]) == 0) {
3542 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3543 file, linenum, args[1]);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
3547 free(curproxy->email_alert.myhostname);
3548 curproxy->email_alert.myhostname = strdup(args[2]);
3549 }
Simon Horman64e34162015-02-06 11:11:57 +09003550 else if (!strcmp(args[1], "level")) {
3551 curproxy->email_alert.level = get_log_level(args[2]);
3552 if (curproxy->email_alert.level < 0) {
3553 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3554 file, linenum, args[1], args[2]);
3555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
3557 }
3558 }
Simon Horman9dc49962015-01-30 11:22:59 +09003559 else if (!strcmp(args[1], "to")) {
3560 if (*(args[1]) == 0) {
3561 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3562 file, linenum, args[1]);
3563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
3565 }
3566 free(curproxy->email_alert.to);
3567 curproxy->email_alert.to = strdup(args[2]);
3568 }
3569 else {
3570 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3571 file, linenum, args[1]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
Simon Horman64e34162015-02-06 11:11:57 +09003575 /* Indicate that the email_alert is at least partially configured */
3576 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003577 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003578 else if (!strcmp(args[0], "external-check")) {
3579 if (*(args[1]) == 0) {
3580 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3581 file, linenum, args[0]);
3582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
3584 }
3585
3586 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003587 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003588 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003589 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003590 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3591 file, linenum, args[1]);
3592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
3594 }
3595 free(curproxy->check_command);
3596 curproxy->check_command = strdup(args[2]);
3597 }
3598 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003599 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003600 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003601 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003602 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3603 file, linenum, args[1]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607 free(curproxy->check_path);
3608 curproxy->check_path = strdup(args[2]);
3609 }
3610 else {
3611 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3612 file, linenum, args[1]);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003617 else if (!strcmp(args[0], "persist")) { /* persist */
3618 if (*(args[1]) == 0) {
3619 Alert("parsing [%s:%d] : missing persist method.\n",
3620 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003623 }
3624
3625 if (!strncmp(args[1], "rdp-cookie", 10)) {
3626 curproxy->options2 |= PR_O2_RDPC_PRST;
3627
Emeric Brunb982a3d2010-01-04 15:45:53 +01003628 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003629 const char *beg, *end;
3630
3631 beg = args[1] + 11;
3632 end = strchr(beg, ')');
3633
William Lallemanddf1425a2015-04-28 20:17:49 +02003634 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3635 goto out;
3636
Emeric Brun647caf12009-06-30 17:57:00 +02003637 if (!end || end == beg) {
3638 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3639 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003642 }
3643
3644 free(curproxy->rdp_cookie_name);
3645 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3646 curproxy->rdp_cookie_len = end-beg;
3647 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003648 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003649 free(curproxy->rdp_cookie_name);
3650 curproxy->rdp_cookie_name = strdup("msts");
3651 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3652 }
3653 else { /* syntax */
3654 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3655 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003658 }
3659 }
3660 else {
3661 Alert("parsing [%s:%d] : unknown persist method.\n",
3662 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003665 }
3666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003668 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
3671 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003672 else if (!strcmp(args[0], "load-server-state-from-file")) {
3673 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3674 err_code |= ERR_WARN;
3675 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3676 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3677 }
3678 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3679 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3680 }
3681 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3682 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3683 }
3684 else {
3685 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3686 file, linenum, args[0], args[1]);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690 }
3691 else if (!strcmp(args[0], "server-state-file-name")) {
3692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3693 err_code |= ERR_WARN;
3694 if (*(args[1]) == 0) {
3695 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3696 file, linenum, args[0]);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700 else if (!strcmp(args[1], "use-backend-name"))
3701 curproxy->server_state_file_name = strdup(curproxy->id);
3702 else
3703 curproxy->server_state_file_name = strdup(args[1]);
3704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003706 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003708
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003710 if (curproxy == &defproxy) {
3711 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715
William Lallemand1a748ae2015-05-19 16:37:23 +02003716 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3717 goto out;
3718
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 if (*(args[4]) == 0) {
3720 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3721 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003725 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 curproxy->capture_name = strdup(args[2]);
3727 curproxy->capture_namelen = strlen(curproxy->capture_name);
3728 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 curproxy->to_log |= LW_COOKIE;
3730 }
3731 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3732 struct cap_hdr *hdr;
3733
3734 if (curproxy == &defproxy) {
3735 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 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 }
3739
William Lallemand1a748ae2015-05-19 16:37:23 +02003740 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3741 goto out;
3742
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3744 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3745 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 }
3749
Vincent Bernat02779b62016-04-03 13:48:43 +02003750 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 hdr->next = curproxy->req_cap;
3752 hdr->name = strdup(args[3]);
3753 hdr->namelen = strlen(args[3]);
3754 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003755 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 hdr->index = curproxy->nb_req_cap++;
3757 curproxy->req_cap = hdr;
3758 curproxy->to_log |= LW_REQHDR;
3759 }
3760 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3761 struct cap_hdr *hdr;
3762
3763 if (curproxy == &defproxy) {
3764 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 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
3768
William Lallemand1a748ae2015-05-19 16:37:23 +02003769 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3770 goto out;
3771
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3773 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3774 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003778 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 hdr->next = curproxy->rsp_cap;
3780 hdr->name = strdup(args[3]);
3781 hdr->namelen = strlen(args[3]);
3782 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003783 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 hdr->index = curproxy->nb_rsp_cap++;
3785 curproxy->rsp_cap = hdr;
3786 curproxy->to_log |= LW_RSPHDR;
3787 }
3788 else {
3789 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3790 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 }
3794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798
William Lallemanddf1425a2015-04-28 20:17:49 +02003799 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3800 goto out;
3801
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 if (*(args[1]) == 0) {
3803 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3804 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 }
3808 curproxy->conn_retries = atol(args[1]);
3809 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003810 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003811 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003812
3813 if (curproxy == &defproxy) {
3814 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
3817 }
3818
Willy Tarreau20b0de52012-12-24 15:45:22 +01003819 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003820 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003821 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3822 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3823 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3824 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003825 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 +01003826 file, linenum, args[0]);
3827 err_code |= ERR_WARN;
3828 }
3829
Willy Tarreauff011f22011-01-06 17:51:27 +01003830 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003831
Willy Tarreauff011f22011-01-06 17:51:27 +01003832 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003833 err_code |= ERR_ALERT | ERR_ABORT;
3834 goto out;
3835 }
3836
Willy Tarreau5002f572014-04-23 01:32:02 +02003837 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003838 err_code |= warnif_cond_conflicts(rule->cond,
3839 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3840 file, linenum);
3841
Willy Tarreauff011f22011-01-06 17:51:27 +01003842 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003843 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003844 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003845 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003846
3847 if (curproxy == &defproxy) {
3848 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852
3853 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003854 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003855 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3856 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003857 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3858 file, linenum, args[0]);
3859 err_code |= ERR_WARN;
3860 }
3861
3862 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3863
3864 if (!rule) {
3865 err_code |= ERR_ALERT | ERR_ABORT;
3866 goto out;
3867 }
3868
3869 err_code |= warnif_cond_conflicts(rule->cond,
3870 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3871 file, linenum);
3872
3873 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3874 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003875 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3876 /* set the header name and length into the proxy structure */
3877 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3878 err_code |= ERR_WARN;
3879
3880 if (!*args[1]) {
3881 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3882 file, linenum, args[0]);
3883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
3885 }
3886
3887 /* set the desired header name */
3888 free(curproxy->server_id_hdr_name);
3889 curproxy->server_id_hdr_name = strdup(args[1]);
3890 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3891 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003892 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003893 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003894
Willy Tarreaub099aca2008-10-12 17:26:37 +02003895 if (curproxy == &defproxy) {
3896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003899 }
3900
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003901 /* emulate "block" using "http-request block". Since these rules are supposed to
3902 * be processed before all http-request rules, we put them into their own list
3903 * and will insert them at the end.
3904 */
3905 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3906 if (!rule) {
3907 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003908 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003909 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003910 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3911 err_code |= warnif_cond_conflicts(rule->cond,
3912 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3913 file, linenum);
3914 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003915
3916 if (!already_warned(WARN_BLOCK_DEPRECATED))
3917 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]);
3918
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003919 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003920 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003921 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003922
Cyril Bonté99ed3272010-01-24 23:29:44 +01003923 if (curproxy == &defproxy) {
3924 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928
Willy Tarreaube4653b2015-05-28 15:26:58 +02003929 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003930 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3931 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003934 }
3935
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003936 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003937 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003938 err_code |= warnif_cond_conflicts(rule->cond,
3939 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3940 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003941 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003942 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003943 struct switching_rule *rule;
3944
Willy Tarreaub099aca2008-10-12 17:26:37 +02003945 if (curproxy == &defproxy) {
3946 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003949 }
3950
Willy Tarreau55ea7572007-06-17 19:56:27 +02003951 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003953
3954 if (*(args[1]) == 0) {
3955 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003958 }
3959
Willy Tarreauf51658d2014-04-23 01:21:56 +02003960 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3961 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3962 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3963 file, linenum, errmsg);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003967
Willy Tarreauf51658d2014-04-23 01:21:56 +02003968 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003969 }
3970
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003971 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02003972 rule->cond = cond;
3973 rule->be.name = strdup(args[1]);
3974 LIST_INIT(&rule->list);
3975 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3976 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003977 else if (strcmp(args[0], "use-server") == 0) {
3978 struct server_rule *rule;
3979
3980 if (curproxy == &defproxy) {
3981 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984 }
3985
3986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3987 err_code |= ERR_WARN;
3988
3989 if (*(args[1]) == 0) {
3990 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
3993 }
3994
3995 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3996 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3997 file, linenum, args[0]);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
4001
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004002 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4003 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4004 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
4008
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004009 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004010
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004011 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004012 rule->cond = cond;
4013 rule->srv.name = strdup(args[1]);
4014 LIST_INIT(&rule->list);
4015 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4016 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4017 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004018 else if ((!strcmp(args[0], "force-persist")) ||
4019 (!strcmp(args[0], "ignore-persist"))) {
4020 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004021
4022 if (curproxy == &defproxy) {
4023 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027
4028 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4029 err_code |= ERR_WARN;
4030
Willy Tarreauef6494c2010-01-28 17:12:36 +01004031 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004032 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4033 file, linenum, args[0]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004038 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4039 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4040 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004045 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4046 * where force-persist is applied.
4047 */
4048 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004049
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004050 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004051 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004052 if (!strcmp(args[0], "force-persist")) {
4053 rule->type = PERSIST_TYPE_FORCE;
4054 } else {
4055 rule->type = PERSIST_TYPE_IGNORE;
4056 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004057 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004058 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004059 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004060 else if (!strcmp(args[0], "stick-table")) {
4061 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004062 struct proxy *other;
4063
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004064 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004065 if (other) {
4066 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4067 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4068 err_code |= ERR_ALERT | ERR_FATAL;
4069 goto out;
4070 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004071
Emeric Brun32da3c42010-09-23 18:39:19 +02004072 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004073 curproxy->table.type = (unsigned int)-1;
4074 while (*args[myidx]) {
4075 const char *err;
4076
4077 if (strcmp(args[myidx], "size") == 0) {
4078 myidx++;
4079 if (!*(args[myidx])) {
4080 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4081 file, linenum, args[myidx-1]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4086 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4087 file, linenum, *err, args[myidx-1]);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004091 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004092 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004093 else if (strcmp(args[myidx], "peers") == 0) {
4094 myidx++;
Godbach50523162013-12-11 19:48:57 +08004095 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004096 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4097 file, linenum, args[myidx-1]);
4098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Godbach50523162013-12-11 19:48:57 +08004100 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004101 curproxy->table.peers.name = strdup(args[myidx++]);
4102 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004103 else if (strcmp(args[myidx], "expire") == 0) {
4104 myidx++;
4105 if (!*(args[myidx])) {
4106 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4107 file, linenum, args[myidx-1]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
4111 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4112 if (err) {
4113 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4114 file, linenum, *err, args[myidx-1]);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004118 if (val > INT_MAX) {
4119 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4120 file, linenum, val);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
4123 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004125 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004126 }
4127 else if (strcmp(args[myidx], "nopurge") == 0) {
4128 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004129 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004130 }
4131 else if (strcmp(args[myidx], "type") == 0) {
4132 myidx++;
4133 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4134 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4135 file, linenum, args[myidx]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004139 /* myidx already points to next arg */
4140 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004141 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004142 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004143 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004144
4145 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004146 nw = args[myidx];
4147 while (*nw) {
4148 /* the "store" keyword supports a comma-separated list */
4149 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004150 sa = NULL; /* store arg */
4151 while (*nw && *nw != ',') {
4152 if (*nw == '(') {
4153 *nw = 0;
4154 sa = ++nw;
4155 while (*nw != ')') {
4156 if (!*nw) {
4157 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4158 file, linenum, args[0], cw);
4159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
4161 }
4162 nw++;
4163 }
4164 *nw = '\0';
4165 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004166 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004167 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004168 if (*nw)
4169 *nw++ = '\0';
4170 type = stktable_get_data_type(cw);
4171 if (type < 0) {
4172 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4173 file, linenum, args[0], cw);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
Willy Tarreauac782882010-06-20 10:41:54 +02004177
4178 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4179 switch (err) {
4180 case PE_NONE: break;
4181 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004182 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4183 file, linenum, args[0], cw);
4184 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004185 break;
4186
4187 case PE_ARG_MISSING:
4188 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4189 file, linenum, args[0], cw);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192
4193 case PE_ARG_NOT_USED:
4194 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4195 file, linenum, args[0], cw);
4196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
4198
4199 default:
4200 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4201 file, linenum, args[0], cw);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004204 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004205 }
4206 myidx++;
4207 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004208 else {
4209 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4210 file, linenum, args[myidx]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004213 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004214 }
4215
4216 if (!curproxy->table.size) {
4217 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4218 file, linenum);
4219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
4221 }
4222
4223 if (curproxy->table.type == (unsigned int)-1) {
4224 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4225 file, linenum);
4226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
4228 }
4229 }
4230 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004231 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004232 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004233 int myidx = 0;
4234 const char *name = NULL;
4235 int flags;
4236
4237 if (curproxy == &defproxy) {
4238 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
4241 }
4242
4243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4244 err_code |= ERR_WARN;
4245 goto out;
4246 }
4247
4248 myidx++;
4249 if ((strcmp(args[myidx], "store") == 0) ||
4250 (strcmp(args[myidx], "store-request") == 0)) {
4251 myidx++;
4252 flags = STK_IS_STORE;
4253 }
4254 else if (strcmp(args[myidx], "store-response") == 0) {
4255 myidx++;
4256 flags = STK_IS_STORE | STK_ON_RSP;
4257 }
4258 else if (strcmp(args[myidx], "match") == 0) {
4259 myidx++;
4260 flags = STK_IS_MATCH;
4261 }
4262 else if (strcmp(args[myidx], "on") == 0) {
4263 myidx++;
4264 flags = STK_IS_MATCH | STK_IS_STORE;
4265 }
4266 else {
4267 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
4272 if (*(args[myidx]) == 0) {
4273 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
4276 }
4277
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004278 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004279 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004280 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004281 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
4285
4286 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004287 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4288 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4289 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004290 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004291 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004292 goto out;
4293 }
4294 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004295 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4296 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4297 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004298 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004299 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004300 goto out;
4301 }
4302 }
4303
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004304 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004305 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004306
Emeric Brunb982a3d2010-01-04 15:45:53 +01004307 if (strcmp(args[myidx], "table") == 0) {
4308 myidx++;
4309 name = args[myidx++];
4310 }
4311
Willy Tarreauef6494c2010-01-28 17:12:36 +01004312 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004313 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4314 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4315 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004316 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004317 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004318 goto out;
4319 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004320 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004321 else if (*(args[myidx])) {
4322 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4323 file, linenum, args[0], args[myidx]);
4324 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004325 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004326 goto out;
4327 }
Emeric Brun97679e72010-09-23 17:56:44 +02004328 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004329 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004330 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004331 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004332
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004333 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004334 rule->cond = cond;
4335 rule->expr = expr;
4336 rule->flags = flags;
4337 rule->table.name = name ? strdup(name) : NULL;
4338 LIST_INIT(&rule->list);
4339 if (flags & STK_ON_RSP)
4340 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4341 else
4342 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4343 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 else if (!strcmp(args[0], "stats")) {
4345 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4346 curproxy->uri_auth = NULL; /* we must detach from the default config */
4347
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004348 if (!*args[1]) {
4349 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004350 } else if (!strcmp(args[1], "admin")) {
4351 struct stats_admin_rule *rule;
4352
4353 if (curproxy == &defproxy) {
4354 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
4357 }
4358
4359 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4360 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4361 err_code |= ERR_ALERT | ERR_ABORT;
4362 goto out;
4363 }
4364
4365 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4366 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4367 file, linenum, args[0], args[1]);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004371 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4372 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4373 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
4376 }
4377
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004378 err_code |= warnif_cond_conflicts(cond,
4379 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4380 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004381
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004382 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004383 rule->cond = cond;
4384 LIST_INIT(&rule->list);
4385 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004386 } else if (!strcmp(args[1], "uri")) {
4387 if (*(args[2]) == 0) {
4388 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4392 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_ABORT;
4394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 }
4396 } else if (!strcmp(args[1], "realm")) {
4397 if (*(args[2]) == 0) {
4398 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4402 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_ALERT | ERR_ABORT;
4404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004406 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004407 unsigned interval;
4408
4409 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4410 if (err) {
4411 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4412 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004415 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_ABORT;
4418 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004419 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004420 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004421 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004422
4423 if (curproxy == &defproxy) {
4424 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 }
4428
4429 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4430 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4431 err_code |= ERR_ALERT | ERR_ABORT;
4432 goto out;
4433 }
4434
Willy Tarreauff011f22011-01-06 17:51:27 +01004435 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004436 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004437 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4438 file, linenum, args[0]);
4439 err_code |= ERR_WARN;
4440 }
4441
Willy Tarreauff011f22011-01-06 17:51:27 +01004442 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004443
Willy Tarreauff011f22011-01-06 17:51:27 +01004444 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004445 err_code |= ERR_ALERT | ERR_ABORT;
4446 goto out;
4447 }
4448
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004449 err_code |= warnif_cond_conflicts(rule->cond,
4450 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4451 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004452 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004453
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 } else if (!strcmp(args[1], "auth")) {
4455 if (*(args[2]) == 0) {
4456 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4460 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_ALERT | ERR_ABORT;
4462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 }
4464 } else if (!strcmp(args[1], "scope")) {
4465 if (*(args[2]) == 0) {
4466 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004469 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_ABORT;
4472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 }
4474 } else if (!strcmp(args[1], "enable")) {
4475 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_ABORT;
4478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004480 } else if (!strcmp(args[1], "hide-version")) {
4481 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4482 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_ABORT;
4484 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004485 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004486 } else if (!strcmp(args[1], "show-legends")) {
4487 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4488 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4489 err_code |= ERR_ALERT | ERR_ABORT;
4490 goto out;
4491 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004492 } else if (!strcmp(args[1], "show-node")) {
4493
4494 if (*args[2]) {
4495 int i;
4496 char c;
4497
4498 for (i=0; args[2][i]; i++) {
4499 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004500 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4501 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004502 break;
4503 }
4504
4505 if (!i || args[2][i]) {
4506 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4507 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4508 file, linenum, args[0], args[1]);
4509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
4511 }
4512 }
4513
4514 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4515 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4516 err_code |= ERR_ALERT | ERR_ABORT;
4517 goto out;
4518 }
4519 } else if (!strcmp(args[1], "show-desc")) {
4520 char *desc = NULL;
4521
4522 if (*args[2]) {
4523 int i, len=0;
4524 char *d;
4525
Willy Tarreau348acfe2014-04-14 15:00:39 +02004526 for (i = 2; *args[i]; i++)
4527 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004528
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004529 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004530
Willy Tarreau348acfe2014-04-14 15:00:39 +02004531 d += snprintf(d, desc + len - d, "%s", args[2]);
4532 for (i = 3; *args[i]; i++)
4533 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004534 }
4535
4536 if (!*args[2] && !global.desc)
4537 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4538 file, linenum, args[1]);
4539 else {
4540 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4541 free(desc);
4542 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4543 err_code |= ERR_ALERT | ERR_ABORT;
4544 goto out;
4545 }
4546 free(desc);
4547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004549stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004550 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 +01004551 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004554 }
4555 }
4556 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004557 int optnum;
4558
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004559 if (*(args[1]) == '\0') {
4560 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4561 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004565
4566 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4567 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004568 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4569 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4570 file, linenum, cfg_opts[optnum].name);
4571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
4573 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004574 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4575 goto out;
4576
Willy Tarreau93893792009-07-23 13:19:11 +02004577 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4578 err_code |= ERR_WARN;
4579 goto out;
4580 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004581
Willy Tarreau3842f002009-06-14 11:39:52 +02004582 curproxy->no_options &= ~cfg_opts[optnum].val;
4583 curproxy->options &= ~cfg_opts[optnum].val;
4584
4585 switch (kwm) {
4586 case KWM_STD:
4587 curproxy->options |= cfg_opts[optnum].val;
4588 break;
4589 case KWM_NO:
4590 curproxy->no_options |= cfg_opts[optnum].val;
4591 break;
4592 case KWM_DEF: /* already cleared */
4593 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004594 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004595
Willy Tarreau93893792009-07-23 13:19:11 +02004596 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004597 }
4598 }
4599
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004600 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4601 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004602 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4603 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4604 file, linenum, cfg_opts2[optnum].name);
4605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
4607 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004608 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4609 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004610 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4611 err_code |= ERR_WARN;
4612 goto out;
4613 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004614
Willy Tarreau3842f002009-06-14 11:39:52 +02004615 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4616 curproxy->options2 &= ~cfg_opts2[optnum].val;
4617
4618 switch (kwm) {
4619 case KWM_STD:
4620 curproxy->options2 |= cfg_opts2[optnum].val;
4621 break;
4622 case KWM_NO:
4623 curproxy->no_options2 |= cfg_opts2[optnum].val;
4624 break;
4625 case KWM_DEF: /* already cleared */
4626 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004627 }
Willy Tarreau93893792009-07-23 13:19:11 +02004628 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004629 }
4630 }
4631
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004632 /* HTTP options override each other. They can be cancelled using
4633 * "no option xxx" which only switches to default mode if the mode
4634 * was this one (useful for cancelling options set in defaults
4635 * sections).
4636 */
4637 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004638 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4639 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004640 if (kwm == KWM_STD) {
4641 curproxy->options &= ~PR_O_HTTP_MODE;
4642 curproxy->options |= PR_O_HTTP_PCL;
4643 goto out;
4644 }
4645 else if (kwm == KWM_NO) {
4646 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4647 curproxy->options &= ~PR_O_HTTP_MODE;
4648 goto out;
4649 }
4650 }
4651 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004652 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4653 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004654 if (kwm == KWM_STD) {
4655 curproxy->options &= ~PR_O_HTTP_MODE;
4656 curproxy->options |= PR_O_HTTP_FCL;
4657 goto out;
4658 }
4659 else if (kwm == KWM_NO) {
4660 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4661 curproxy->options &= ~PR_O_HTTP_MODE;
4662 goto out;
4663 }
4664 }
4665 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004666 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4667 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004668 if (kwm == KWM_STD) {
4669 curproxy->options &= ~PR_O_HTTP_MODE;
4670 curproxy->options |= PR_O_HTTP_SCL;
4671 goto out;
4672 }
4673 else if (kwm == KWM_NO) {
4674 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4675 curproxy->options &= ~PR_O_HTTP_MODE;
4676 goto out;
4677 }
4678 }
4679 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004680 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4681 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004682 if (kwm == KWM_STD) {
4683 curproxy->options &= ~PR_O_HTTP_MODE;
4684 curproxy->options |= PR_O_HTTP_KAL;
4685 goto out;
4686 }
4687 else if (kwm == KWM_NO) {
4688 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4689 curproxy->options &= ~PR_O_HTTP_MODE;
4690 goto out;
4691 }
4692 }
4693 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004694 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4695 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004696 if (kwm == KWM_STD) {
4697 curproxy->options &= ~PR_O_HTTP_MODE;
4698 curproxy->options |= PR_O_HTTP_TUN;
4699 goto out;
4700 }
4701 else if (kwm == KWM_NO) {
4702 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4703 curproxy->options &= ~PR_O_HTTP_MODE;
4704 goto out;
4705 }
4706 }
4707
Joseph Lynch726ab712015-05-11 23:25:34 -07004708 /* Redispatch can take an integer argument that control when the
4709 * resispatch occurs. All values are relative to the retries option.
4710 * This can be cancelled using "no option xxx".
4711 */
4712 if (strcmp(args[1], "redispatch") == 0) {
4713 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4714 err_code |= ERR_WARN;
4715 goto out;
4716 }
4717
4718 curproxy->no_options &= ~PR_O_REDISP;
4719 curproxy->options &= ~PR_O_REDISP;
4720
4721 switch (kwm) {
4722 case KWM_STD:
4723 curproxy->options |= PR_O_REDISP;
4724 curproxy->redispatch_after = -1;
4725 if(*args[2]) {
4726 curproxy->redispatch_after = atol(args[2]);
4727 }
4728 break;
4729 case KWM_NO:
4730 curproxy->no_options |= PR_O_REDISP;
4731 curproxy->redispatch_after = 0;
4732 break;
4733 case KWM_DEF: /* already cleared */
4734 break;
4735 }
4736 goto out;
4737 }
4738
Willy Tarreau3842f002009-06-14 11:39:52 +02004739 if (kwm != KWM_STD) {
4740 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004741 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004744 }
4745
Emeric Brun3a058f32009-06-30 18:26:00 +02004746 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004747 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004749 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004750 if (*(args[2]) != '\0') {
4751 if (!strcmp(args[2], "clf")) {
4752 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004753 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004754 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004755 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004758 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004759 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4760 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004761 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004762 if (curproxy->conf.logformat_string != default_http_log_format &&
4763 curproxy->conf.logformat_string != default_tcp_log_format &&
4764 curproxy->conf.logformat_string != clf_http_log_format)
4765 free(curproxy->conf.logformat_string);
4766 curproxy->conf.logformat_string = logformat;
4767
4768 free(curproxy->conf.lfs_file);
4769 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4770 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004771 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004772 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004774 if (curproxy->conf.logformat_string != default_http_log_format &&
4775 curproxy->conf.logformat_string != default_tcp_log_format &&
4776 curproxy->conf.logformat_string != clf_http_log_format)
4777 free(curproxy->conf.logformat_string);
4778 curproxy->conf.logformat_string = default_tcp_log_format;
4779
4780 free(curproxy->conf.lfs_file);
4781 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4782 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004783
4784 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4785 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004788 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004789 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004790 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004791
William Lallemanddf1425a2015-04-28 20:17:49 +02004792 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4793 goto out;
4794
Willy Tarreau13943ab2006-12-31 00:24:10 +01004795 if (curproxy->cap & PR_CAP_FE)
4796 curproxy->options |= PR_O_TCP_CLI_KA;
4797 if (curproxy->cap & PR_CAP_BE)
4798 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 }
4800 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004801 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_WARN;
4803
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004805 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004806 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004807 curproxy->options2 &= ~PR_O2_CHK_ANY;
4808 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 if (!*args[2]) { /* no argument */
4810 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4811 curproxy->check_len = strlen(DEF_CHECK_REQ);
4812 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004813 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004814 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004816 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004818 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 if (*args[4])
4820 reqlen += strlen(args[4]);
4821 else
4822 reqlen += strlen("HTTP/1.0");
4823
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004824 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004826 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004828 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4829 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004830 }
4831 else if (!strcmp(args[1], "ssl-hello-chk")) {
4832 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004833 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004835
Willy Tarreaua534fea2008-08-03 12:19:50 +02004836 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004837 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004838 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004839 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004840
4841 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 }
Willy Tarreau23677902007-05-08 23:50:35 +02004844 else if (!strcmp(args[1], "smtpchk")) {
4845 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004846 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004847 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004848 curproxy->options2 &= ~PR_O2_CHK_ANY;
4849 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004850
4851 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4852 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4853 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4854 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4855 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4856 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004857 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004858 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4859 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4860 } else {
4861 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4862 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4863 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4864 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4865 }
4866 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004867 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4868 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004869 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004870 else if (!strcmp(args[1], "pgsql-check")) {
4871 /* use PostgreSQL request to check servers' health */
4872 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4873 err_code |= ERR_WARN;
4874
4875 free(curproxy->check_req);
4876 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004877 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004878 curproxy->options2 |= PR_O2_PGSQL_CHK;
4879
4880 if (*(args[2])) {
4881 int cur_arg = 2;
4882
4883 while (*(args[cur_arg])) {
4884 if (strcmp(args[cur_arg], "user") == 0) {
4885 char * packet;
4886 uint32_t packet_len;
4887 uint32_t pv;
4888
4889 /* suboption header - needs additional argument for it */
4890 if (*(args[cur_arg+1]) == 0) {
4891 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4892 file, linenum, args[0], args[1], args[cur_arg]);
4893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
4895 }
4896
4897 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4898 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4899 pv = htonl(0x30000); /* protocol version 3.0 */
4900
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004901 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004902
4903 memcpy(packet + 4, &pv, 4);
4904
4905 /* copy "user" */
4906 memcpy(packet + 8, "user", 4);
4907
4908 /* copy username */
4909 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4910
4911 free(curproxy->check_req);
4912 curproxy->check_req = packet;
4913 curproxy->check_len = packet_len;
4914
4915 packet_len = htonl(packet_len);
4916 memcpy(packet, &packet_len, 4);
4917 cur_arg += 2;
4918 } else {
4919 /* unknown suboption - catchall */
4920 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4921 file, linenum, args[0], args[1]);
4922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
4924 }
4925 } /* end while loop */
4926 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004927 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4928 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004929 }
4930
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004931 else if (!strcmp(args[1], "redis-check")) {
4932 /* use REDIS PING request to check servers' health */
4933 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4934 err_code |= ERR_WARN;
4935
4936 free(curproxy->check_req);
4937 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004938 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004939 curproxy->options2 |= PR_O2_REDIS_CHK;
4940
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004941 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004942 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4943 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004944
4945 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4946 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004947 }
4948
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004949 else if (!strcmp(args[1], "mysql-check")) {
4950 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004951 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4952 err_code |= ERR_WARN;
4953
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004954 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004955 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004956 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004957 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004958
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004959 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004960 * const char mysql40_client_auth_pkt[] = {
4961 * "\x0e\x00\x00" // packet length
4962 * "\x01" // packet number
4963 * "\x00\x00" // client capabilities
4964 * "\x00\x00\x01" // max packet
4965 * "haproxy\x00" // username (null terminated string)
4966 * "\x00" // filler (always 0x00)
4967 * "\x01\x00\x00" // packet length
4968 * "\x00" // packet number
4969 * "\x01" // COM_QUIT command
4970 * };
4971 */
4972
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004973 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4974 * const char mysql41_client_auth_pkt[] = {
4975 * "\x0e\x00\x00\" // packet length
4976 * "\x01" // packet number
4977 * "\x00\x00\x00\x00" // client capabilities
4978 * "\x00\x00\x00\x01" // max packet
4979 * "\x21" // character set (UTF-8)
4980 * char[23] // All zeroes
4981 * "haproxy\x00" // username (null terminated string)
4982 * "\x00" // filler (always 0x00)
4983 * "\x01\x00\x00" // packet length
4984 * "\x00" // packet number
4985 * "\x01" // COM_QUIT command
4986 * };
4987 */
4988
4989
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004990 if (*(args[2])) {
4991 int cur_arg = 2;
4992
4993 while (*(args[cur_arg])) {
4994 if (strcmp(args[cur_arg], "user") == 0) {
4995 char *mysqluser;
4996 int packetlen, reqlen, userlen;
4997
4998 /* suboption header - needs additional argument for it */
4999 if (*(args[cur_arg+1]) == 0) {
5000 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5001 file, linenum, args[0], args[1], args[cur_arg]);
5002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
5004 }
5005 mysqluser = args[cur_arg + 1];
5006 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005007
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005008 if (*(args[cur_arg+2])) {
5009 if (!strcmp(args[cur_arg+2], "post-41")) {
5010 packetlen = userlen + 7 + 27;
5011 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005012
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005013 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005014 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005015 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005016
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005017 snprintf(curproxy->check_req, 4, "%c%c%c",
5018 ((unsigned char) packetlen & 0xff),
5019 ((unsigned char) (packetlen >> 8) & 0xff),
5020 ((unsigned char) (packetlen >> 16) & 0xff));
5021
5022 curproxy->check_req[3] = 1;
5023 curproxy->check_req[5] = 130;
5024 curproxy->check_req[11] = 1;
5025 curproxy->check_req[12] = 33;
5026 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5027 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5028 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5029 cur_arg += 3;
5030 } else {
5031 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
5035 } else {
5036 packetlen = userlen + 7;
5037 reqlen = packetlen + 9;
5038
5039 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005040 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005041 curproxy->check_len = reqlen;
5042
5043 snprintf(curproxy->check_req, 4, "%c%c%c",
5044 ((unsigned char) packetlen & 0xff),
5045 ((unsigned char) (packetlen >> 8) & 0xff),
5046 ((unsigned char) (packetlen >> 16) & 0xff));
5047
5048 curproxy->check_req[3] = 1;
5049 curproxy->check_req[5] = 128;
5050 curproxy->check_req[8] = 1;
5051 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5052 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5053 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5054 cur_arg += 2;
5055 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005056 } else {
5057 /* unknown suboption - catchall */
5058 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5059 file, linenum, args[0], args[1]);
5060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
5062 }
5063 } /* end while loop */
5064 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005065 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005066 else if (!strcmp(args[1], "ldap-check")) {
5067 /* use LDAP request to check servers' health */
5068 free(curproxy->check_req);
5069 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005070 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005071 curproxy->options2 |= PR_O2_LDAP_CHK;
5072
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005073 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005074 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5075 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005076 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5077 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005078 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005079 else if (!strcmp(args[1], "tcp-check")) {
5080 /* use raw TCPCHK send/expect to check servers' health */
5081 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5082 err_code |= ERR_WARN;
5083
5084 free(curproxy->check_req);
5085 curproxy->check_req = NULL;
5086 curproxy->options2 &= ~PR_O2_CHK_ANY;
5087 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005088 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5089 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005090 }
Simon Horman98637e52014-06-20 12:30:16 +09005091 else if (!strcmp(args[1], "external-check")) {
5092 /* excute an external command to check servers' health */
5093 free(curproxy->check_req);
5094 curproxy->check_req = NULL;
5095 curproxy->options2 &= ~PR_O2_CHK_ANY;
5096 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005097 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5098 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005099 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005100 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005101 int cur_arg;
5102
5103 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5104 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005105 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005106
Willy Tarreau87cf5142011-08-19 22:57:24 +02005107 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005108
5109 free(curproxy->fwdfor_hdr_name);
5110 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5111 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5112
5113 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5114 cur_arg = 2;
5115 while (*(args[cur_arg])) {
5116 if (!strcmp(args[cur_arg], "except")) {
5117 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005118 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005119 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5120 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005123 }
5124 /* flush useless bits */
5125 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005126 cur_arg += 2;
5127 } else if (!strcmp(args[cur_arg], "header")) {
5128 /* suboption header - needs additional argument for it */
5129 if (*(args[cur_arg+1]) == 0) {
5130 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5131 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005134 }
5135 free(curproxy->fwdfor_hdr_name);
5136 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5137 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5138 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005139 } else if (!strcmp(args[cur_arg], "if-none")) {
5140 curproxy->options &= ~PR_O_FF_ALWAYS;
5141 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005142 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005143 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005144 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005145 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005148 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005149 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005150 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005151 else if (!strcmp(args[1], "originalto")) {
5152 int cur_arg;
5153
5154 /* insert x-original-to field, but not for the IP address listed as an except.
5155 * set default options (ie: bitfield, header name, etc)
5156 */
5157
5158 curproxy->options |= PR_O_ORGTO;
5159
5160 free(curproxy->orgto_hdr_name);
5161 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5162 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5163
Willy Tarreau87cf5142011-08-19 22:57:24 +02005164 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005165 cur_arg = 2;
5166 while (*(args[cur_arg])) {
5167 if (!strcmp(args[cur_arg], "except")) {
5168 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005169 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 +02005170 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5171 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005174 }
5175 /* flush useless bits */
5176 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5177 cur_arg += 2;
5178 } else if (!strcmp(args[cur_arg], "header")) {
5179 /* suboption header - needs additional argument for it */
5180 if (*(args[cur_arg+1]) == 0) {
5181 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5182 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005185 }
5186 free(curproxy->orgto_hdr_name);
5187 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5188 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5189 cur_arg += 2;
5190 } else {
5191 /* unknown suboption - catchall */
5192 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5193 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005196 }
5197 } /* end while loop */
5198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 else {
5200 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
Willy Tarreau93893792009-07-23 13:19:11 +02005204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005206 else if (!strcmp(args[0], "default_backend")) {
5207 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005208 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005209
5210 if (*(args[1]) == 0) {
5211 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005214 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005215 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005216 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005217
5218 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5219 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005224
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005225 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5226 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 +01005227 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005228 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 /* enable reconnections to dispatch */
5230 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005231
5232 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005235 else if (!strcmp(args[0], "http-reuse")) {
5236 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5237 err_code |= ERR_WARN;
5238
5239 if (strcmp(args[1], "never") == 0) {
5240 /* enable a graceful server shutdown on an HTTP 404 response */
5241 curproxy->options &= ~PR_O_REUSE_MASK;
5242 curproxy->options |= PR_O_REUSE_NEVR;
5243 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5244 goto out;
5245 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005246 else if (strcmp(args[1], "safe") == 0) {
5247 /* enable a graceful server shutdown on an HTTP 404 response */
5248 curproxy->options &= ~PR_O_REUSE_MASK;
5249 curproxy->options |= PR_O_REUSE_SAFE;
5250 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5251 goto out;
5252 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005253 else if (strcmp(args[1], "aggressive") == 0) {
5254 curproxy->options &= ~PR_O_REUSE_MASK;
5255 curproxy->options |= PR_O_REUSE_AGGR;
5256 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5257 goto out;
5258 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005259 else if (strcmp(args[1], "always") == 0) {
5260 /* enable a graceful server shutdown on an HTTP 404 response */
5261 curproxy->options &= ~PR_O_REUSE_MASK;
5262 curproxy->options |= PR_O_REUSE_ALWS;
5263 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5264 goto out;
5265 }
5266 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005267 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005272 else if (!strcmp(args[0], "http-check")) {
5273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005274 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005275
5276 if (strcmp(args[1], "disable-on-404") == 0) {
5277 /* enable a graceful server shutdown on an HTTP 404 response */
5278 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005279 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5280 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005281 }
Willy Tarreauef781042010-01-27 11:53:01 +01005282 else if (strcmp(args[1], "send-state") == 0) {
5283 /* enable emission of the apparent state of a server in HTTP checks */
5284 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005285 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5286 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005287 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005288 else if (strcmp(args[1], "expect") == 0) {
5289 const char *ptr_arg;
5290 int cur_arg;
5291
5292 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5293 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
5296 }
5297
5298 cur_arg = 2;
5299 /* consider exclamation marks, sole or at the beginning of a word */
5300 while (*(ptr_arg = args[cur_arg])) {
5301 while (*ptr_arg == '!') {
5302 curproxy->options2 ^= PR_O2_EXP_INV;
5303 ptr_arg++;
5304 }
5305 if (*ptr_arg)
5306 break;
5307 cur_arg++;
5308 }
5309 /* now ptr_arg points to the beginning of a word past any possible
5310 * exclamation mark, and cur_arg is the argument which holds this word.
5311 */
5312 if (strcmp(ptr_arg, "status") == 0) {
5313 if (!*(args[cur_arg + 1])) {
5314 Alert("parsing [%s:%d] : '%s %s %s' expects <string> 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_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005320 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005321 curproxy->expect_str = strdup(args[cur_arg + 1]);
5322 }
5323 else if (strcmp(ptr_arg, "string") == 0) {
5324 if (!*(args[cur_arg + 1])) {
5325 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5326 file, linenum, args[0], args[1], ptr_arg);
5327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
5329 }
5330 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005331 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005332 curproxy->expect_str = strdup(args[cur_arg + 1]);
5333 }
5334 else if (strcmp(ptr_arg, "rstatus") == 0) {
5335 if (!*(args[cur_arg + 1])) {
5336 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5337 file, linenum, args[0], args[1], ptr_arg);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005342 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005343 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005344 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005345 free(curproxy->expect_regex);
5346 curproxy->expect_regex = NULL;
5347 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005348 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005349 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5350 error = NULL;
5351 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5352 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5353 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5354 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357 }
5358 }
5359 else if (strcmp(ptr_arg, "rstring") == 0) {
5360 if (!*(args[cur_arg + 1])) {
5361 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5362 file, linenum, args[0], args[1], ptr_arg);
5363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
5365 }
5366 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005367 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005368 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005369 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005370 free(curproxy->expect_regex);
5371 curproxy->expect_regex = NULL;
5372 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005373 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005374 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5375 error = NULL;
5376 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5377 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5378 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5379 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383 }
5384 else {
5385 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5386 file, linenum, args[0], args[1], ptr_arg);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 }
5390 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005391 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005392 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 +02005393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005395 }
5396 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005397 else if (!strcmp(args[0], "tcp-check")) {
5398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5399 err_code |= ERR_WARN;
5400
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005401 if (strcmp(args[1], "comment") == 0) {
5402 int cur_arg;
5403 struct tcpcheck_rule *tcpcheck;
5404
5405 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005406 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005407 tcpcheck->action = TCPCHK_ACT_COMMENT;
5408
5409 if (!*args[cur_arg + 1]) {
5410 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5411 file, linenum, args[cur_arg]);
5412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
5414 }
5415
5416 tcpcheck->comment = strdup(args[cur_arg + 1]);
5417
5418 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005419 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5420 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005421 }
5422 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005423 const char *ptr_arg;
5424 int cur_arg;
5425 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005426
5427 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005428 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5429 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5430 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5431 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5432 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005433
Willy Tarreau5581c272015-05-13 12:24:53 +02005434 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5435 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5436 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5437 file, linenum);
5438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005440 }
5441
5442 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005443 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005444 tcpcheck->action = TCPCHK_ACT_CONNECT;
5445
5446 /* parsing each parameters to fill up the rule */
5447 while (*(ptr_arg = args[cur_arg])) {
5448 /* tcp port */
5449 if (strcmp(args[cur_arg], "port") == 0) {
5450 if ( (atol(args[cur_arg + 1]) > 65535) ||
5451 (atol(args[cur_arg + 1]) < 1) ){
5452 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5453 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457 tcpcheck->port = atol(args[cur_arg + 1]);
5458 cur_arg += 2;
5459 }
5460 /* send proxy protocol */
5461 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5462 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5463 cur_arg++;
5464 }
5465#ifdef USE_OPENSSL
5466 else if (strcmp(args[cur_arg], "ssl") == 0) {
5467 curproxy->options |= PR_O_TCPCHK_SSL;
5468 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5469 cur_arg++;
5470 }
5471#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005472 /* comment for this tcpcheck line */
5473 else if (strcmp(args[cur_arg], "comment") == 0) {
5474 if (!*args[cur_arg + 1]) {
5475 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5476 file, linenum, args[cur_arg]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480 tcpcheck->comment = strdup(args[cur_arg + 1]);
5481 cur_arg += 2;
5482 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005483 else {
5484#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005485 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 +01005486#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005487 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 +01005488#endif /* USE_OPENSSL */
5489 file, linenum, args[0], args[1], args[cur_arg]);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
5493
5494 }
5495
5496 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5497 }
5498 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005499 if (! *(args[2]) ) {
5500 /* SEND string expected */
5501 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5502 file, linenum, args[0], args[1], args[2]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 } else {
5506 struct tcpcheck_rule *tcpcheck;
5507
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005508 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005509
5510 tcpcheck->action = TCPCHK_ACT_SEND;
5511 tcpcheck->string_len = strlen(args[2]);
5512 tcpcheck->string = strdup(args[2]);
5513 tcpcheck->expect_regex = NULL;
5514
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005515 /* comment for this tcpcheck line */
5516 if (strcmp(args[3], "comment") == 0) {
5517 if (!*args[4]) {
5518 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5519 file, linenum, args[3]);
5520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522 }
5523 tcpcheck->comment = strdup(args[4]);
5524 }
5525
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005526 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5527 }
5528 }
5529 else if (strcmp(args[1], "send-binary") == 0) {
5530 if (! *(args[2]) ) {
5531 /* SEND binary string expected */
5532 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5533 file, linenum, args[0], args[1], args[2]);
5534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536 } else {
5537 struct tcpcheck_rule *tcpcheck;
5538 char *err = NULL;
5539
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005540 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005541
5542 tcpcheck->action = TCPCHK_ACT_SEND;
5543 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5544 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5545 file, linenum, args[0], args[1], args[2], err);
5546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
5549 tcpcheck->expect_regex = NULL;
5550
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005551 /* comment for this tcpcheck line */
5552 if (strcmp(args[3], "comment") == 0) {
5553 if (!*args[4]) {
5554 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5555 file, linenum, args[3]);
5556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
5558 }
5559 tcpcheck->comment = strdup(args[4]);
5560 }
5561
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005562 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5563 }
5564 }
5565 else if (strcmp(args[1], "expect") == 0) {
5566 const char *ptr_arg;
5567 int cur_arg;
5568 int inverse = 0;
5569
5570 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5571 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
5575
5576 cur_arg = 2;
5577 /* consider exclamation marks, sole or at the beginning of a word */
5578 while (*(ptr_arg = args[cur_arg])) {
5579 while (*ptr_arg == '!') {
5580 inverse = !inverse;
5581 ptr_arg++;
5582 }
5583 if (*ptr_arg)
5584 break;
5585 cur_arg++;
5586 }
5587 /* now ptr_arg points to the beginning of a word past any possible
5588 * exclamation mark, and cur_arg is the argument which holds this word.
5589 */
5590 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005591 struct tcpcheck_rule *tcpcheck;
5592 char *err = NULL;
5593
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005594 if (!*(args[cur_arg + 1])) {
5595 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5596 file, linenum, args[0], args[1], ptr_arg);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005600
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005601 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005602
5603 tcpcheck->action = TCPCHK_ACT_EXPECT;
5604 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5605 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5606 file, linenum, args[0], args[1], args[2], err);
5607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
5609 }
5610 tcpcheck->expect_regex = NULL;
5611 tcpcheck->inverse = inverse;
5612
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005613 /* tcpcheck comment */
5614 cur_arg += 2;
5615 if (strcmp(args[cur_arg], "comment") == 0) {
5616 if (!*args[cur_arg + 1]) {
5617 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5618 file, linenum, args[cur_arg + 1]);
5619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
5622 tcpcheck->comment = strdup(args[cur_arg + 1]);
5623 }
5624
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005625 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5626 }
5627 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005628 struct tcpcheck_rule *tcpcheck;
5629
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005630 if (!*(args[cur_arg + 1])) {
5631 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5632 file, linenum, args[0], args[1], ptr_arg);
5633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
5635 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005636
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005637 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005638
5639 tcpcheck->action = TCPCHK_ACT_EXPECT;
5640 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5641 tcpcheck->string = strdup(args[cur_arg + 1]);
5642 tcpcheck->expect_regex = NULL;
5643 tcpcheck->inverse = inverse;
5644
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005645 /* tcpcheck comment */
5646 cur_arg += 2;
5647 if (strcmp(args[cur_arg], "comment") == 0) {
5648 if (!*args[cur_arg + 1]) {
5649 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5650 file, linenum, args[cur_arg + 1]);
5651 err_code |= ERR_ALERT | ERR_FATAL;
5652 goto out;
5653 }
5654 tcpcheck->comment = strdup(args[cur_arg + 1]);
5655 }
5656
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005657 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5658 }
5659 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005660 struct tcpcheck_rule *tcpcheck;
5661
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005662 if (!*(args[cur_arg + 1])) {
5663 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5664 file, linenum, args[0], args[1], ptr_arg);
5665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
5667 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005668
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005669 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005670
5671 tcpcheck->action = TCPCHK_ACT_EXPECT;
5672 tcpcheck->string_len = 0;
5673 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005674 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5675 error = NULL;
5676 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5677 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5678 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5679 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
5683 tcpcheck->inverse = inverse;
5684
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005685 /* tcpcheck comment */
5686 cur_arg += 2;
5687 if (strcmp(args[cur_arg], "comment") == 0) {
5688 if (!*args[cur_arg + 1]) {
5689 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5690 file, linenum, args[cur_arg + 1]);
5691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
5693 }
5694 tcpcheck->comment = strdup(args[cur_arg + 1]);
5695 }
5696
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005697 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5698 }
5699 else {
5700 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5701 file, linenum, args[0], args[1], ptr_arg);
5702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
5705 }
5706 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005707 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
5710 }
5711 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005712 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005713 if (curproxy == &defproxy) {
5714 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005717 }
5718
Willy Tarreaub80c2302007-11-30 20:51:32 +01005719 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005720 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005721
5722 if (strcmp(args[1], "fail") == 0) {
5723 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005724 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005725 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5726 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005729 }
5730
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005731 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5732 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5733 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005736 }
5737 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5738 }
5739 else {
5740 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005743 }
5744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745#ifdef TPROXY
5746 else if (!strcmp(args[0], "transparent")) {
5747 /* enable transparent proxy connections */
5748 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005749 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 }
5752#endif
5753 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005754 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005755 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005756
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 if (*(args[1]) == 0) {
5758 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005759 err_code |= ERR_ALERT | ERR_FATAL;
5760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 }
5762 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005766 else if (!strcmp(args[0], "backlog")) { /* backlog */
5767 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005769
5770 if (*(args[1]) == 0) {
5771 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005774 }
5775 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5777 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005778 }
Willy Tarreau86034312006-12-29 00:10:33 +01005779 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005780 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005781 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005782
Willy Tarreau86034312006-12-29 00:10:33 +01005783 if (*(args[1]) == 0) {
5784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005787 }
5788 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005789 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5790 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005791 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5793 if (*(args[1]) == 0) {
5794 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005798 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5799 if (err) {
5800 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5801 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005804 }
5805 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005806 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
5809 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005810 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005811 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005812 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005813
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 if (curproxy == &defproxy) {
5815 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005819 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005820 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005821
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005822 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005823 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005824 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005825 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005826 goto out;
5827 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005828
5829 proto = protocol_by_family(sk->ss_family);
5830 if (!proto || !proto->connect) {
5831 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5832 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005833 err_code |= ERR_ALERT | ERR_FATAL;
5834 goto out;
5835 }
5836
5837 if (port1 != port2) {
5838 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5839 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005843
5844 if (!port1) {
5845 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5846 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005847 err_code |= ERR_ALERT | ERR_FATAL;
5848 goto out;
5849 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005850
William Lallemanddf1425a2015-04-28 20:17:49 +02005851 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5852 goto out;
5853
Willy Tarreaud5191e72010-02-09 20:50:45 +01005854 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005855 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856 }
5857 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005858 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005859 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005860
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005861 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5862 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005863 err_code |= ERR_ALERT | ERR_FATAL;
5864 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005867 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005868 /**
5869 * The syntax for hash-type config element is
5870 * hash-type {map-based|consistent} [[<algo>] avalanche]
5871 *
5872 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5873 */
5874 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005875
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5877 err_code |= ERR_WARN;
5878
5879 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005880 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5881 }
5882 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005883 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5884 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005885 else if (strcmp(args[1], "avalanche") == 0) {
5886 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]);
5887 err_code |= ERR_ALERT | ERR_FATAL;
5888 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005889 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005890 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005891 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005892 err_code |= ERR_ALERT | ERR_FATAL;
5893 goto out;
5894 }
Bhaskar98634f02013-10-29 23:30:51 -04005895
5896 /* set the hash function to use */
5897 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005898 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005899 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005900
5901 /* if consistent with no argument, then avalanche modifier is also applied */
5902 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5903 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005904 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005905 /* set the hash function */
5906 if (!strcmp(args[2], "sdbm")) {
5907 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5908 }
5909 else if (!strcmp(args[2], "djb2")) {
5910 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005911 }
5912 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005913 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005914 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005915 else if (!strcmp(args[2], "crc32")) {
5916 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5917 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005918 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005919 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 -05005920 err_code |= ERR_ALERT | ERR_FATAL;
5921 goto out;
5922 }
5923
5924 /* set the hash modifier */
5925 if (!strcmp(args[3], "avalanche")) {
5926 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5927 }
5928 else if (*args[3]) {
5929 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005933 }
William Lallemanda73203e2012-03-12 12:48:57 +01005934 }
William Lallemanda73203e2012-03-12 12:48:57 +01005935 else if (strcmp(args[0], "unique-id-format") == 0) {
5936 if (!*(args[1])) {
5937 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
5940 }
William Lallemand3203ff42012-11-11 17:30:56 +01005941 if (*(args[2])) {
5942 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5943 err_code |= ERR_ALERT | ERR_FATAL;
5944 goto out;
5945 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005946 free(curproxy->conf.uniqueid_format_string);
5947 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005948
Willy Tarreau62a61232013-04-12 18:13:46 +02005949 free(curproxy->conf.uif_file);
5950 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5951 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005952 }
William Lallemanda73203e2012-03-12 12:48:57 +01005953
5954 else if (strcmp(args[0], "unique-id-header") == 0) {
5955 if (!*(args[1])) {
5956 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
5959 }
5960 free(curproxy->header_unique_id);
5961 curproxy->header_unique_id = strdup(args[1]);
5962 }
5963
William Lallemand723b73a2012-02-08 16:37:49 +01005964 else if (strcmp(args[0], "log-format") == 0) {
5965 if (!*(args[1])) {
5966 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5967 err_code |= ERR_ALERT | ERR_FATAL;
5968 goto out;
5969 }
William Lallemand3203ff42012-11-11 17:30:56 +01005970 if (*(args[2])) {
5971 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005975
Willy Tarreau62a61232013-04-12 18:13:46 +02005976 if (curproxy->conf.logformat_string != default_http_log_format &&
5977 curproxy->conf.logformat_string != default_tcp_log_format &&
5978 curproxy->conf.logformat_string != clf_http_log_format)
5979 free(curproxy->conf.logformat_string);
5980 curproxy->conf.logformat_string = strdup(args[1]);
5981
5982 free(curproxy->conf.lfs_file);
5983 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5984 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005985
5986 /* get a chance to improve log-format error reporting by
5987 * reporting the correct line-number when possible.
5988 */
5989 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5990 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5991 file, linenum, curproxy->id);
5992 err_code |= ERR_WARN;
5993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005995 else if (!strcmp(args[0], "log-format-sd")) {
5996 if (!*(args[1])) {
5997 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001 if (*(args[2])) {
6002 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6003 err_code |= ERR_ALERT | ERR_FATAL;
6004 goto out;
6005 }
6006
6007 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6008 free(curproxy->conf.logformat_sd_string);
6009 curproxy->conf.logformat_sd_string = strdup(args[1]);
6010
6011 free(curproxy->conf.lfsd_file);
6012 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6013 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6014
6015 /* get a chance to improve log-format-sd error reporting by
6016 * reporting the correct line-number when possible.
6017 */
6018 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6019 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6020 file, linenum, curproxy->id);
6021 err_code |= ERR_WARN;
6022 }
6023 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006024 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6025 if (*(args[1]) == 0) {
6026 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
6029 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006030 chunk_destroy(&curproxy->log_tag);
6031 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006032 }
William Lallemand0f99e342011-10-12 17:50:54 +02006033 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6034 /* delete previous herited or defined syslog servers */
6035 struct logsrv *back;
6036
6037 if (*(args[1]) != 0) {
6038 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6039 err_code |= ERR_ALERT | ERR_FATAL;
6040 goto out;
6041 }
6042
William Lallemand723b73a2012-02-08 16:37:49 +01006043 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6044 LIST_DEL(&tmplogsrv->list);
6045 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006046 }
6047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006049 struct logsrv *logsrv;
6050
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006052 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006053 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006054 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006055 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006056 LIST_INIT(&node->list);
6057 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
6060 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006061 struct sockaddr_storage *sk;
6062 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006063 int arg = 0;
6064 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006065
Vincent Bernat02779b62016-04-03 13:48:43 +02006066 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067
Willy Tarreau18324f52014-06-27 18:10:07 +02006068 /* just after the address, a length may be specified */
6069 if (strcmp(args[arg+2], "len") == 0) {
6070 len = atoi(args[arg+3]);
6071 if (len < 80 || len > 65535) {
6072 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6073 file, linenum, args[arg+3]);
6074 err_code |= ERR_ALERT | ERR_FATAL;
6075 goto out;
6076 }
6077 logsrv->maxlen = len;
6078
6079 /* skip these two args */
6080 arg += 2;
6081 }
6082 else
6083 logsrv->maxlen = MAX_SYSLOG_LEN;
6084
6085 if (logsrv->maxlen > global.max_syslog_len) {
6086 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006087 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6088 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6089 logline = my_realloc2(logline, global.max_syslog_len + 1);
6090 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006091 }
6092
Dragan Dosen1322d092015-09-22 16:05:32 +02006093 /* after the length, a format may be specified */
6094 if (strcmp(args[arg+2], "format") == 0) {
6095 logsrv->format = get_log_format(args[arg+3]);
6096 if (logsrv->format < 0) {
6097 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6098 err_code |= ERR_ALERT | ERR_FATAL;
6099 goto out;
6100 }
6101
6102 /* skip these two args */
6103 arg += 2;
6104 }
6105
William Lallemanddf1425a2015-04-28 20:17:49 +02006106 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6107 goto out;
6108
Willy Tarreau18324f52014-06-27 18:10:07 +02006109 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006110 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006111 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006112 err_code |= ERR_ALERT | ERR_FATAL;
6113 goto out;
6114
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115 }
6116
William Lallemand0f99e342011-10-12 17:50:54 +02006117 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006118 if (*(args[arg+3])) {
6119 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006120 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006121 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
6124
Willy Tarreaubaaee002006-06-26 02:48:02 +02006125 }
6126 }
6127
William Lallemand0f99e342011-10-12 17:50:54 +02006128 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006129 if (*(args[arg+4])) {
6130 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006131 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006132 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006133 err_code |= ERR_ALERT | ERR_FATAL;
6134 goto out;
6135
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006136 }
6137 }
6138
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006139 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006140 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006141 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006142 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006143 goto out;
6144 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006145
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006146 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006147
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006148 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006149 if (port1 != port2) {
6150 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6151 file, linenum, args[0], args[1]);
6152 err_code |= ERR_ALERT | ERR_FATAL;
6153 goto out;
6154 }
6155
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006156 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006157 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 }
William Lallemand0f99e342011-10-12 17:50:54 +02006159
6160 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 }
6162 else {
6163 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6164 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006165 err_code |= ERR_ALERT | ERR_FATAL;
6166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167 }
6168 }
6169 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006170 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006171 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006172 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006173 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006174
Willy Tarreau977b8e42006-12-29 14:19:17 +01006175 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006177
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006179 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6180 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006181 err_code |= ERR_ALERT | ERR_FATAL;
6182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006184
6185 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006186 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6187 free(curproxy->conn_src.iface_name);
6188 curproxy->conn_src.iface_name = NULL;
6189 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006190
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006191 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006192 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006193 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006194 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006195 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006196 goto out;
6197 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006198
6199 proto = protocol_by_family(sk->ss_family);
6200 if (!proto || !proto->connect) {
6201 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006202 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006203 err_code |= ERR_ALERT | ERR_FATAL;
6204 goto out;
6205 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006206
6207 if (port1 != port2) {
6208 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6209 file, linenum, args[0], args[1]);
6210 err_code |= ERR_ALERT | ERR_FATAL;
6211 goto out;
6212 }
6213
Willy Tarreauef9a3602012-12-08 22:29:20 +01006214 curproxy->conn_src.source_addr = *sk;
6215 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006216
6217 cur_arg = 2;
6218 while (*(args[cur_arg])) {
6219 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006220#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006221 if (!*args[cur_arg + 1]) {
6222 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6223 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006226 }
6227
6228 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006229 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6230 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006231 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006232 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6233 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006234 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6235 char *name, *end;
6236
6237 name = args[cur_arg+1] + 7;
6238 while (isspace(*name))
6239 name++;
6240
6241 end = name;
6242 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6243 end++;
6244
Willy Tarreauef9a3602012-12-08 22:29:20 +01006245 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6246 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6247 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6248 curproxy->conn_src.bind_hdr_len = end - name;
6249 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6250 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6251 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006252
6253 /* now look for an occurrence number */
6254 while (isspace(*end))
6255 end++;
6256 if (*end == ',') {
6257 end++;
6258 name = end;
6259 if (*end == '-')
6260 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006261 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006262 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006263 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006264 }
6265
Willy Tarreauef9a3602012-12-08 22:29:20 +01006266 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006267 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6268 " occurrences values smaller than %d.\n",
6269 file, linenum, MAX_HDR_HISTORY);
6270 err_code |= ERR_ALERT | ERR_FATAL;
6271 goto out;
6272 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006273 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006274 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006275
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006276 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006277 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006278 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006279 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006280 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006281 goto out;
6282 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006283
6284 proto = protocol_by_family(sk->ss_family);
6285 if (!proto || !proto->connect) {
6286 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6287 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006288 err_code |= ERR_ALERT | ERR_FATAL;
6289 goto out;
6290 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006291
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006292 if (port1 != port2) {
6293 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6294 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006295 err_code |= ERR_ALERT | ERR_FATAL;
6296 goto out;
6297 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006298 curproxy->conn_src.tproxy_addr = *sk;
6299 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006300 }
6301 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006302#else /* no TPROXY support */
6303 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006304 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006305 err_code |= ERR_ALERT | ERR_FATAL;
6306 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006307#endif
6308 cur_arg += 2;
6309 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006310 }
6311
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006312 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6313#ifdef SO_BINDTODEVICE
6314 if (!*args[cur_arg + 1]) {
6315 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6316 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006317 err_code |= ERR_ALERT | ERR_FATAL;
6318 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006319 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006320 free(curproxy->conn_src.iface_name);
6321 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6322 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006323 global.last_checks |= LSTCHK_NETADM;
6324#else
6325 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6326 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006327 err_code |= ERR_ALERT | ERR_FATAL;
6328 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006329#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006330 cur_arg += 2;
6331 continue;
6332 }
6333 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006334 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006335 err_code |= ERR_ALERT | ERR_FATAL;
6336 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006339 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6340 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6341 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006342 err_code |= ERR_ALERT | ERR_FATAL;
6343 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006349 err_code |= ERR_ALERT | ERR_FATAL;
6350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352
6353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
6366 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 }
6373 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006375 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006376 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
6380 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006382 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006383 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006384 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006387 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006389 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006390 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006391 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006392 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006398 err_code |= ERR_ALERT | ERR_FATAL;
6399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006401
6402 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006403 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006404 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006405 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 }
6408 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006410 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006411 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006412 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 }
6415 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006417 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006418 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006419 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 }
6422 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006423 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006424 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006425 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006426 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 }
6429 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006431 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006432 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006433 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006436 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006437 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006438 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006439 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006440 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006441 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006444 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006445
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 if (curproxy == &defproxy) {
6447 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006451 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006452 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 if (*(args[1]) == 0) {
6455 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006456 err_code |= ERR_ALERT | ERR_FATAL;
6457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006459
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006460 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006461 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6462 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6463 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006464 err_code |= ERR_ALERT | ERR_FATAL;
6465 goto out;
6466 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006467 err_code |= warnif_cond_conflicts(cond,
6468 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6469 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006470 }
6471 else if (*args[2]) {
6472 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6473 file, linenum, args[0], args[2]);
6474 err_code |= ERR_ALERT | ERR_FATAL;
6475 goto out;
6476 }
6477
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006478 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006479 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006480 wl->s = strdup(args[1]);
6481 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006482 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 }
6484 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006486 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6487 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006488 err_code |= ERR_ALERT | ERR_FATAL;
6489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006491
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006493 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006494 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006495 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 }
6498 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006500 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006501 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006502 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 }
6505 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006507 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006508 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006509 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006514 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6515 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006516 err_code |= ERR_ALERT | ERR_FATAL;
6517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006518 }
6519
Willy Tarreauade5ec42010-01-28 19:33:49 +01006520 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006521 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006522 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006523 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525 }
6526 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006527 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006528 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006529 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006530 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006532 }
6533 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006534 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006535 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006536 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006537 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006539 }
6540 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006541 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006542
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543 if (curproxy == &defproxy) {
6544 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006545 err_code |= ERR_ALERT | ERR_FATAL;
6546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006548 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006549 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550
Willy Tarreaubaaee002006-06-26 02:48:02 +02006551 if (*(args[1]) == 0) {
6552 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006553 err_code |= ERR_ALERT | ERR_FATAL;
6554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 }
6556
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006557 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006558 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6559 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6560 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006561 err_code |= ERR_ALERT | ERR_FATAL;
6562 goto out;
6563 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006564 err_code |= warnif_cond_conflicts(cond,
6565 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6566 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006567 }
6568 else if (*args[2]) {
6569 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6570 file, linenum, args[0], args[2]);
6571 err_code |= ERR_ALERT | ERR_FATAL;
6572 goto out;
6573 }
6574
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006575 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006576 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006577 wl->s = strdup(args[1]);
6578 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579 }
6580 else if (!strcmp(args[0], "errorloc") ||
6581 !strcmp(args[0], "errorloc302") ||
6582 !strcmp(args[0], "errorloc303")) { /* error location */
6583 int errnum, errlen;
6584 char *err;
6585
Willy Tarreau977b8e42006-12-29 14:19:17 +01006586 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006587 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006588
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006590 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006591 err_code |= ERR_ALERT | ERR_FATAL;
6592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006593 }
6594
6595 errnum = atol(args[1]);
6596 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006597 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6598 err = malloc(errlen);
6599 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006601 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6602 err = malloc(errlen);
6603 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604 }
6605
Willy Tarreau0f772532006-12-23 20:51:41 +01006606 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6607 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006608 chunk_destroy(&curproxy->errmsg[rc]);
6609 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006610 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006612 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006613
6614 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006615 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6616 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617 free(err);
6618 }
6619 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006620 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6621 int errnum, errlen, fd;
6622 char *err;
6623 struct stat stat;
6624
6625 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006626 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006627
6628 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006629 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006630 err_code |= ERR_ALERT | ERR_FATAL;
6631 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006632 }
6633
6634 fd = open(args[2], O_RDONLY);
6635 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6636 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6637 file, linenum, args[2], args[1]);
6638 if (fd >= 0)
6639 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006640 err_code |= ERR_ALERT | ERR_FATAL;
6641 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006642 }
6643
Willy Tarreau27a674e2009-08-17 07:23:33 +02006644 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006645 errlen = stat.st_size;
6646 } else {
6647 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006648 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006649 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006650 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006651 }
6652
6653 err = malloc(errlen); /* malloc() must succeed during parsing */
6654 errnum = read(fd, err, errlen);
6655 if (errnum != errlen) {
6656 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6657 file, linenum, args[2], args[1]);
6658 close(fd);
6659 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006660 err_code |= ERR_ALERT | ERR_FATAL;
6661 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006662 }
6663 close(fd);
6664
6665 errnum = atol(args[1]);
6666 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6667 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006668 chunk_destroy(&curproxy->errmsg[rc]);
6669 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006670 break;
6671 }
6672 }
6673
6674 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006675 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6676 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006677 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006678 free(err);
6679 }
6680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006681 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006682 struct cfg_kw_list *kwl;
6683 int index;
6684
6685 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6686 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6687 if (kwl->kw[index].section != CFG_LISTEN)
6688 continue;
6689 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6690 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006691 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006692 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006693 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006694 err_code |= ERR_ALERT | ERR_FATAL;
6695 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006696 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006697 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006698 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006699 err_code |= ERR_WARN;
6700 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006701 }
Willy Tarreau93893792009-07-23 13:19:11 +02006702 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006703 }
6704 }
6705 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006706
Willy Tarreau6daf3432008-01-22 16:44:08 +01006707 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006708 err_code |= ERR_ALERT | ERR_FATAL;
6709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710 }
Willy Tarreau93893792009-07-23 13:19:11 +02006711 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006712 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006713 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006714}
6715
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006716int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006717cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6718{
6719#ifdef CONFIG_HAP_NS
6720 const char *err;
6721 const char *item = args[0];
6722
6723 if (!strcmp(item, "namespace_list")) {
6724 return 0;
6725 }
6726 else if (!strcmp(item, "namespace")) {
6727 size_t idx = 1;
6728 const char *current;
6729 while (*(current = args[idx++])) {
6730 err = invalid_char(current);
6731 if (err) {
6732 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6733 file, linenum, *err, item, current);
6734 return ERR_ALERT | ERR_FATAL;
6735 }
6736
6737 if (netns_store_lookup(current, strlen(current))) {
6738 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6739 file, linenum, current);
6740 return ERR_ALERT | ERR_FATAL;
6741 }
6742 if (!netns_store_insert(current)) {
6743 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6744 file, linenum, current);
6745 return ERR_ALERT | ERR_FATAL;
6746 }
6747 }
6748 }
6749
6750 return 0;
6751#else
6752 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6753 file, linenum);
6754 return ERR_ALERT | ERR_FATAL;
6755#endif
6756}
6757
6758int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006759cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6760{
6761
6762 int err_code = 0;
6763 const char *err;
6764
6765 if (!strcmp(args[0], "userlist")) { /* new userlist */
6766 struct userlist *newul;
6767
6768 if (!*args[1]) {
6769 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6770 file, linenum, args[0]);
6771 err_code |= ERR_ALERT | ERR_FATAL;
6772 goto out;
6773 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006774 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6775 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006776
6777 err = invalid_char(args[1]);
6778 if (err) {
6779 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6780 file, linenum, *err, args[0], args[1]);
6781 err_code |= ERR_ALERT | ERR_FATAL;
6782 goto out;
6783 }
6784
6785 for (newul = userlist; newul; newul = newul->next)
6786 if (!strcmp(newul->name, args[1])) {
6787 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6788 file, linenum, args[1]);
6789 err_code |= ERR_WARN;
6790 goto out;
6791 }
6792
Vincent Bernat02779b62016-04-03 13:48:43 +02006793 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006794 if (!newul) {
6795 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6796 err_code |= ERR_ALERT | ERR_ABORT;
6797 goto out;
6798 }
6799
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006801 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6803 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006804 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006805 goto out;
6806 }
6807
6808 newul->next = userlist;
6809 userlist = newul;
6810
6811 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006812 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006814 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006815
6816 if (!*args[1]) {
6817 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6818 file, linenum, args[0]);
6819 err_code |= ERR_ALERT | ERR_FATAL;
6820 goto out;
6821 }
6822
6823 err = invalid_char(args[1]);
6824 if (err) {
6825 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6826 file, linenum, *err, args[0], args[1]);
6827 err_code |= ERR_ALERT | ERR_FATAL;
6828 goto out;
6829 }
6830
William Lallemand4ac9f542015-05-28 18:03:51 +02006831 if (!userlist)
6832 goto out;
6833
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006834 for (ag = userlist->groups; ag; ag = ag->next)
6835 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006836 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6837 file, linenum, args[1], userlist->name);
6838 err_code |= ERR_ALERT;
6839 goto out;
6840 }
6841
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006842 ag = calloc(1, sizeof(*ag));
6843 if (!ag) {
6844 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6845 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006846 goto out;
6847 }
6848
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006849 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006850 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006851 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6852 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006853 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006854 goto out;
6855 }
6856
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006857 cur_arg = 2;
6858
6859 while (*args[cur_arg]) {
6860 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006861 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006862 cur_arg += 2;
6863 continue;
6864 } else {
6865 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6866 file, linenum, args[0]);
6867 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006868 free(ag->groupusers);
6869 free(ag->name);
6870 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006871 goto out;
6872 }
6873 }
6874
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006875 ag->next = userlist->groups;
6876 userlist->groups = ag;
6877
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006878 } else if (!strcmp(args[0], "user")) { /* new user */
6879 struct auth_users *newuser;
6880 int cur_arg;
6881
6882 if (!*args[1]) {
6883 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6884 file, linenum, args[0]);
6885 err_code |= ERR_ALERT | ERR_FATAL;
6886 goto out;
6887 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006888 if (!userlist)
6889 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006890
6891 for (newuser = userlist->users; newuser; newuser = newuser->next)
6892 if (!strcmp(newuser->user, args[1])) {
6893 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6894 file, linenum, args[1], userlist->name);
6895 err_code |= ERR_ALERT;
6896 goto out;
6897 }
6898
Vincent Bernat02779b62016-04-03 13:48:43 +02006899 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006900 if (!newuser) {
6901 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6902 err_code |= ERR_ALERT | ERR_ABORT;
6903 goto out;
6904 }
6905
6906 newuser->user = strdup(args[1]);
6907
6908 newuser->next = userlist->users;
6909 userlist->users = newuser;
6910
6911 cur_arg = 2;
6912
6913 while (*args[cur_arg]) {
6914 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006915#ifdef CONFIG_HAP_CRYPT
6916 if (!crypt("", args[cur_arg + 1])) {
6917 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6918 file, linenum, newuser->user);
6919 err_code |= ERR_ALERT | ERR_FATAL;
6920 goto out;
6921 }
6922#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006923 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6924 file, linenum);
6925 err_code |= ERR_ALERT;
6926#endif
6927 newuser->pass = strdup(args[cur_arg + 1]);
6928 cur_arg += 2;
6929 continue;
6930 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6931 newuser->pass = strdup(args[cur_arg + 1]);
6932 newuser->flags |= AU_O_INSECURE;
6933 cur_arg += 2;
6934 continue;
6935 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006936 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006937 cur_arg += 2;
6938 continue;
6939 } else {
6940 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6941 file, linenum, args[0]);
6942 err_code |= ERR_ALERT | ERR_FATAL;
6943 goto out;
6944 }
6945 }
6946 } else {
6947 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6948 err_code |= ERR_ALERT | ERR_FATAL;
6949 }
6950
6951out:
6952 return err_code;
6953}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954
6955/*
6956 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006957 * Returns the error code, 0 if OK, or any combination of :
6958 * - ERR_ABORT: must abort ASAP
6959 * - ERR_FATAL: we can continue parsing but not start the service
6960 * - ERR_WARN: a warning has been emitted
6961 * - ERR_ALERT: an alert has been emitted
6962 * Only the two first ones can stop processing, the two others are just
6963 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006964 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006965int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006966{
William Lallemand64e84512015-05-12 14:25:37 +02006967 char *thisline;
6968 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006969 FILE *f;
6970 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006971 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006972 struct cfg_section *cs = NULL;
6973 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006974 int readbytes = 0;
6975
6976 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006977 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006978 return -1;
6979 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006980
David Carlier97880bb2016-04-08 10:35:26 +01006981 if ((f=fopen(file,"r")) == NULL) {
6982 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006985
William Lallemandb2f07452015-05-12 14:27:13 +02006986next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006987 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006988 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006989 char *end;
6990 char *args[MAX_LINE_ARGS + 1];
6991 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006992 int dquote = 0; /* double quote */
6993 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006994
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995 linenum++;
6996
6997 end = line + strlen(line);
6998
William Lallemand64e84512015-05-12 14:25:37 +02006999 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007000 /* Check if we reached the limit and the last char is not \n.
7001 * Watch out for the last line without the terminating '\n'!
7002 */
William Lallemand64e84512015-05-12 14:25:37 +02007003 char *newline;
7004 int newlinesize = linesize * 2;
7005
7006 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7007 if (newline == NULL) {
7008 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7009 file, linenum);
7010 err_code |= ERR_ALERT | ERR_FATAL;
7011 continue;
7012 }
7013
7014 readbytes = linesize - 1;
7015 linesize = newlinesize;
7016 thisline = newline;
7017 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007018 }
7019
William Lallemand64e84512015-05-12 14:25:37 +02007020 readbytes = 0;
7021
Willy Tarreaubaaee002006-06-26 02:48:02 +02007022 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007023 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007025
Willy Tarreaubaaee002006-06-26 02:48:02 +02007026 arg = 0;
7027 args[arg] = line;
7028
7029 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007030 if (*line == '"' && !squote) { /* double quote outside single quotes */
7031 if (dquote)
7032 dquote = 0;
7033 else
7034 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007035 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007036 end--;
7037 }
7038 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7039 if (squote)
7040 squote = 0;
7041 else
7042 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007043 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007044 end--;
7045 }
7046 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007047 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7048 * C equivalent value. Other combinations left unchanged (eg: \1).
7049 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007050 int skip = 0;
7051 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7052 *line = line[1];
7053 skip = 1;
7054 }
7055 else if (line[1] == 'r') {
7056 *line = '\r';
7057 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007059 else if (line[1] == 'n') {
7060 *line = '\n';
7061 skip = 1;
7062 }
7063 else if (line[1] == 't') {
7064 *line = '\t';
7065 skip = 1;
7066 }
7067 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007068 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007069 unsigned char hex1, hex2;
7070 hex1 = toupper(line[2]) - '0';
7071 hex2 = toupper(line[3]) - '0';
7072 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7073 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7074 *line = (hex1<<4) + hex2;
7075 skip = 3;
7076 }
7077 else {
7078 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007079 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007081 } else if (line[1] == '"') {
7082 *line = '"';
7083 skip = 1;
7084 } else if (line[1] == '\'') {
7085 *line = '\'';
7086 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007087 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7088 *line = '$';
7089 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007090 }
7091 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007092 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 end -= skip;
7094 }
7095 line++;
7096 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007097 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007098 /* end of string, end of loop */
7099 *line = 0;
7100 break;
7101 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007102 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007103 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007104 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007105 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106 line++;
7107 args[++arg] = line;
7108 }
William Lallemandb2f07452015-05-12 14:27:13 +02007109 else if (dquote && *line == '$') {
7110 /* environment variables are evaluated inside double quotes */
7111 char *var_beg;
7112 char *var_end;
7113 char save_char;
7114 char *value;
7115 int val_len;
7116 int newlinesize;
7117 int braces = 0;
7118
7119 var_beg = line + 1;
7120 var_end = var_beg;
7121
7122 if (*var_beg == '{') {
7123 var_beg++;
7124 var_end++;
7125 braces = 1;
7126 }
7127
7128 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7129 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7130 err_code |= ERR_ALERT | ERR_FATAL;
7131 goto next_line; /* skip current line */
7132 }
7133
7134 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7135 var_end++;
7136
7137 save_char = *var_end;
7138 *var_end = '\0';
7139 value = getenv(var_beg);
7140 *var_end = save_char;
7141 val_len = value ? strlen(value) : 0;
7142
7143 if (braces) {
7144 if (*var_end == '}') {
7145 var_end++;
7146 braces = 0;
7147 } else {
7148 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7149 err_code |= ERR_ALERT | ERR_FATAL;
7150 goto next_line; /* skip current line */
7151 }
7152 }
7153
7154 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7155
7156 /* if not enough space in thisline */
7157 if (newlinesize > linesize) {
7158 char *newline;
7159
7160 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7161 if (newline == NULL) {
7162 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7163 err_code |= ERR_ALERT | ERR_FATAL;
7164 goto next_line; /* slip current line */
7165 }
7166 /* recompute pointers if realloc returns a new pointer */
7167 if (newline != thisline) {
7168 int i;
7169 int diff;
7170
7171 for (i = 0; i <= arg; i++) {
7172 diff = args[i] - thisline;
7173 args[i] = newline + diff;
7174 }
7175
7176 diff = var_end - thisline;
7177 var_end = newline + diff;
7178 diff = end - thisline;
7179 end = newline + diff;
7180 diff = line - thisline;
7181 line = newline + diff;
7182 thisline = newline;
7183 }
7184 linesize = newlinesize;
7185 }
7186
7187 /* insert value inside the line */
7188 memmove(line + val_len, var_end, end - var_end + 1);
7189 memcpy(line, value, val_len);
7190 end += val_len - (var_end - line);
7191 line += val_len;
7192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007193 else {
7194 line++;
7195 }
7196 }
William Lallemandb2f07452015-05-12 14:27:13 +02007197
William Lallemandf9873ba2015-05-05 17:37:14 +02007198 if (dquote) {
7199 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7200 err_code |= ERR_ALERT | ERR_FATAL;
7201 }
7202
7203 if (squote) {
7204 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7205 err_code |= ERR_ALERT | ERR_FATAL;
7206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007207
7208 /* empty line */
7209 if (!**args)
7210 continue;
7211
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007212 if (*line) {
7213 /* we had to stop due to too many args.
7214 * Let's terminate the string, print the offending part then cut the
7215 * last arg.
7216 */
7217 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7218 line++;
7219 *line = '\0';
7220
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007221 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007222 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007223 err_code |= ERR_ALERT | ERR_FATAL;
7224 args[arg] = line;
7225 }
7226
Willy Tarreau540abe42007-05-02 20:50:16 +02007227 /* zero out remaining args and ensure that at least one entry
7228 * is zeroed out.
7229 */
7230 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007231 args[arg] = line;
7232 }
7233
Willy Tarreau3842f002009-06-14 11:39:52 +02007234 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007235 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007236 char *tmp;
7237
Willy Tarreau3842f002009-06-14 11:39:52 +02007238 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007239 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007240 for (arg=0; *args[arg+1]; arg++)
7241 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007242 *tmp = '\0'; // fix the next arg to \0
7243 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007244 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007245 else if (!strcmp(args[0], "default")) {
7246 kwm = KWM_DEF;
7247 for (arg=0; *args[arg+1]; arg++)
7248 args[arg] = args[arg+1]; // shift args after inversion
7249 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007250
William Lallemand0f99e342011-10-12 17:50:54 +02007251 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7252 strcmp(args[0], "log") != 0) {
7253 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007254 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007255 }
7256
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007257 /* detect section start */
7258 list_for_each_entry(ics, &sections, list) {
7259 if (strcmp(args[0], ics->section_name) == 0) {
7260 cursection = ics->section_name;
7261 cs = ics;
7262 break;
7263 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007264 }
7265
Willy Tarreaubaaee002006-06-26 02:48:02 +02007266 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007267 if (cs)
7268 err_code |= cs->section_parser(file, linenum, args, kwm);
7269 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007270 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007271 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007272 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007273
7274 if (err_code & ERR_ABORT)
7275 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007276 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007277 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007278 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007279 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007280 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007281}
7282
Willy Tarreau64ab6072014-09-16 12:17:36 +02007283/* This function propagates processes from frontend <from> to backend <to> so
7284 * that it is always guaranteed that a backend pointed to by a frontend is
7285 * bound to all of its processes. After that, if the target is a "listen"
7286 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007287 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007288 * checked first to ensure that <to> is already bound to all processes of
7289 * <from>, there is no risk of looping and we ensure to follow the shortest
7290 * path to the destination.
7291 *
7292 * It is possible to set <to> to NULL for the first call so that the function
7293 * takes care of visiting the initial frontend in <from>.
7294 *
7295 * It is important to note that the function relies on the fact that all names
7296 * have already been resolved.
7297 */
7298void propagate_processes(struct proxy *from, struct proxy *to)
7299{
7300 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007301
7302 if (to) {
7303 /* check whether we need to go down */
7304 if (from->bind_proc &&
7305 (from->bind_proc & to->bind_proc) == from->bind_proc)
7306 return;
7307
7308 if (!from->bind_proc && !to->bind_proc)
7309 return;
7310
7311 to->bind_proc = from->bind_proc ?
7312 (to->bind_proc | from->bind_proc) : 0;
7313
7314 /* now propagate down */
7315 from = to;
7316 }
7317
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007318 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007319 return;
7320
Willy Tarreauf6b70012014-12-18 14:00:43 +01007321 if (from->state == PR_STSTOPPED)
7322 return;
7323
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324 /* default_backend */
7325 if (from->defbe.be)
7326 propagate_processes(from, from->defbe.be);
7327
7328 /* use_backend */
7329 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007330 if (rule->dynamic)
7331 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007332 to = rule->be.backend;
7333 propagate_processes(from, to);
7334 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007335}
7336
Willy Tarreaubb925012009-07-23 13:36:36 +02007337/*
7338 * Returns the error code, 0 if OK, or any combination of :
7339 * - ERR_ABORT: must abort ASAP
7340 * - ERR_FATAL: we can continue parsing but not start the service
7341 * - ERR_WARN: a warning has been emitted
7342 * - ERR_ALERT: an alert has been emitted
7343 * Only the two first ones can stop processing, the two others are just
7344 * indicators.
7345 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007346int check_config_validity()
7347{
7348 int cfgerr = 0;
7349 struct proxy *curproxy = NULL;
7350 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007351 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007352 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007353 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007354
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007355 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007356 /*
7357 * Now, check for the integrity of all that we have collected.
7358 */
7359
7360 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007361 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007362
Willy Tarreau193b8c62012-11-22 00:17:38 +01007363 if (!global.tune.max_http_hdr)
7364 global.tune.max_http_hdr = MAX_HTTP_HDR;
7365
7366 if (!global.tune.cookie_len)
7367 global.tune.cookie_len = CAPTURE_LEN;
7368
7369 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7370
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007371 /* Post initialisation of the users and groups lists. */
7372 err_code = userlist_postinit();
7373 if (err_code != ERR_NONE)
7374 goto out;
7375
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007376 /* first, we will invert the proxy list order */
7377 curproxy = NULL;
7378 while (proxy) {
7379 struct proxy *next;
7380
7381 next = proxy->next;
7382 proxy->next = curproxy;
7383 curproxy = proxy;
7384 if (!next)
7385 break;
7386 proxy = next;
7387 }
7388
Willy Tarreau419ead82014-09-16 13:41:21 +02007389 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007390 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007391 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007392 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007393 struct act_rule *trule;
7394 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007395 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007396 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007397 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007398
Willy Tarreau050536d2012-10-04 08:47:34 +02007399 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007400 /* proxy ID not set, use automatic numbering with first
7401 * spare entry starting with next_pxid.
7402 */
7403 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7404 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7405 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007406 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007407 next_pxid++;
7408
Willy Tarreau55ea7572007-06-17 19:56:27 +02007409
Willy Tarreaubaaee002006-06-26 02:48:02 +02007410 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007411 /* ensure we don't keep listeners uselessly bound */
7412 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007413 free((void *)curproxy->table.peers.name);
7414 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007415 continue;
7416 }
7417
Willy Tarreau102df612014-05-07 23:56:38 +02007418 /* Check multi-process mode compatibility for the current proxy */
7419
7420 if (curproxy->bind_proc) {
7421 /* an explicit bind-process was specified, let's check how many
7422 * processes remain.
7423 */
David Carliere6c39412015-07-02 07:00:17 +00007424 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007425
7426 curproxy->bind_proc &= nbits(global.nbproc);
7427 if (!curproxy->bind_proc && nbproc == 1) {
7428 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);
7429 curproxy->bind_proc = 1;
7430 }
7431 else if (!curproxy->bind_proc && nbproc > 1) {
7432 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);
7433 curproxy->bind_proc = 0;
7434 }
7435 }
7436
Willy Tarreau3d209582014-05-09 17:06:11 +02007437 /* check and reduce the bind-proc of each listener */
7438 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7439 unsigned long mask;
7440
7441 if (!bind_conf->bind_proc)
7442 continue;
7443
7444 mask = nbits(global.nbproc);
7445 if (curproxy->bind_proc)
7446 mask &= curproxy->bind_proc;
7447 /* mask cannot be null here thanks to the previous checks */
7448
David Carliere6c39412015-07-02 07:00:17 +00007449 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007450 bind_conf->bind_proc &= mask;
7451
7452 if (!bind_conf->bind_proc && nbproc == 1) {
7453 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",
7454 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7455 bind_conf->bind_proc = mask & ~(mask - 1);
7456 }
7457 else if (!bind_conf->bind_proc && nbproc > 1) {
7458 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",
7459 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7460 bind_conf->bind_proc = 0;
7461 }
7462 }
7463
Willy Tarreauff01a212009-03-15 13:46:16 +01007464 switch (curproxy->mode) {
7465 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007466 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007467 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007468 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7469 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007470 cfgerr++;
7471 }
7472
7473 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007474 Warning("config : servers will be ignored for %s '%s'.\n",
7475 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007476 break;
7477
7478 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007479 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007480 break;
7481
7482 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007483 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007484 break;
7485 }
7486
Willy Tarreauf3934b82015-08-11 11:36:45 +02007487 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7488 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7489 proxy_type_str(curproxy), curproxy->id);
7490 err_code |= ERR_WARN;
7491 }
7492
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007493 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007494 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007495 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007496 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7497 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007498 cfgerr++;
7499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007500#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007501 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007502 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7503 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007504 cfgerr++;
7505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007506#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007507 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007508 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7509 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007510 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007511 }
7512 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007513 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007514 /* If no LB algo is set in a backend, and we're not in
7515 * transparent mode, dispatch mode nor proxy mode, we
7516 * want to use balance roundrobin by default.
7517 */
7518 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7519 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007520 }
7521 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007522
Willy Tarreau1620ec32011-08-06 17:05:02 +02007523 if (curproxy->options & PR_O_DISPATCH)
7524 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7525 else if (curproxy->options & PR_O_HTTP_PROXY)
7526 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7527 else if (curproxy->options & PR_O_TRANSP)
7528 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007529
Willy Tarreau1620ec32011-08-06 17:05:02 +02007530 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7531 if (curproxy->options & PR_O_DISABLE404) {
7532 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7533 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7534 err_code |= ERR_WARN;
7535 curproxy->options &= ~PR_O_DISABLE404;
7536 }
7537 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7538 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7539 "send-state", proxy_type_str(curproxy), curproxy->id);
7540 err_code |= ERR_WARN;
7541 curproxy->options &= ~PR_O2_CHK_SNDST;
7542 }
Willy Tarreauef781042010-01-27 11:53:01 +01007543 }
7544
Simon Horman98637e52014-06-20 12:30:16 +09007545 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7546 if (!global.external_check) {
7547 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7548 curproxy->id, "option external-check");
7549 cfgerr++;
7550 }
7551 if (!curproxy->check_command) {
7552 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7553 curproxy->id, "option external-check");
7554 cfgerr++;
7555 }
7556 }
7557
Simon Horman64e34162015-02-06 11:11:57 +09007558 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007559 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7560 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007561 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7562 "'email-alert myhostname', or 'email-alert to' "
7563 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007564 "to be present).\n",
7565 proxy_type_str(curproxy), curproxy->id);
7566 err_code |= ERR_WARN;
7567 free_email_alert(curproxy);
7568 }
7569 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007570 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007571 }
7572
Simon Horman98637e52014-06-20 12:30:16 +09007573 if (curproxy->check_command) {
7574 int clear = 0;
7575 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7576 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7577 "external-check command", proxy_type_str(curproxy), curproxy->id);
7578 err_code |= ERR_WARN;
7579 clear = 1;
7580 }
7581 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007582 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007583 curproxy->id, "external-check command");
7584 cfgerr++;
7585 }
7586 if (clear) {
7587 free(curproxy->check_command);
7588 curproxy->check_command = NULL;
7589 }
7590 }
7591
7592 if (curproxy->check_path) {
7593 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7594 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7595 "external-check path", proxy_type_str(curproxy), curproxy->id);
7596 err_code |= ERR_WARN;
7597 free(curproxy->check_path);
7598 curproxy->check_path = NULL;
7599 }
7600 }
7601
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007602 /* if a default backend was specified, let's find it */
7603 if (curproxy->defbe.name) {
7604 struct proxy *target;
7605
Willy Tarreauafb39922015-05-26 12:04:09 +02007606 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007607 if (!target) {
7608 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7609 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007610 cfgerr++;
7611 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007612 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7613 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007614 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007615 } else if (target->mode != curproxy->mode &&
7616 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7617
7618 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7619 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7620 curproxy->conf.file, curproxy->conf.line,
7621 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7622 target->conf.file, target->conf.line);
7623 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007624 } else {
7625 free(curproxy->defbe.name);
7626 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007627
7628 /* Emit a warning if this proxy also has some servers */
7629 if (curproxy->srv) {
7630 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7631 curproxy->id);
7632 err_code |= ERR_WARN;
7633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007634 }
7635 }
7636
Willy Tarreau55ea7572007-06-17 19:56:27 +02007637 /* find the target proxy for 'use_backend' rules */
7638 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007639 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007640 struct logformat_node *node;
7641 char *pxname;
7642
7643 /* Try to parse the string as a log format expression. If the result
7644 * of the parsing is only one entry containing a simple string, then
7645 * it's a standard string corresponding to a static rule, thus the
7646 * parsing is cancelled and be.name is restored to be resolved.
7647 */
7648 pxname = rule->be.name;
7649 LIST_INIT(&rule->be.expr);
7650 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7651 curproxy->conf.args.file, curproxy->conf.args.line);
7652 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7653
7654 if (!LIST_ISEMPTY(&rule->be.expr)) {
7655 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7656 rule->dynamic = 1;
7657 free(pxname);
7658 continue;
7659 }
7660 /* simple string: free the expression and fall back to static rule */
7661 free(node->arg);
7662 free(node);
7663 }
7664
7665 rule->dynamic = 0;
7666 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007667
Willy Tarreauafb39922015-05-26 12:04:09 +02007668 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007669 if (!target) {
7670 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7671 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007672 cfgerr++;
7673 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007674 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7675 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007676 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007677 } else if (target->mode != curproxy->mode &&
7678 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7679
7680 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7681 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7682 curproxy->conf.file, curproxy->conf.line,
7683 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7684 target->conf.file, target->conf.line);
7685 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007686 } else {
7687 free((void *)rule->be.name);
7688 rule->be.backend = target;
7689 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007690 }
7691
Willy Tarreau64ab6072014-09-16 12:17:36 +02007692 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007693 list_for_each_entry(srule, &curproxy->server_rules, list) {
7694 struct server *target = findserver(curproxy, srule->srv.name);
7695
7696 if (!target) {
7697 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7698 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7699 cfgerr++;
7700 continue;
7701 }
7702 free((void *)srule->srv.name);
7703 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007704 }
7705
Emeric Brunb982a3d2010-01-04 15:45:53 +01007706 /* find the target table for 'stick' rules */
7707 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7708 struct proxy *target;
7709
Emeric Brun1d33b292010-01-04 15:47:17 +01007710 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7711 if (mrule->flags & STK_IS_STORE)
7712 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7713
Emeric Brunb982a3d2010-01-04 15:45:53 +01007714 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007715 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007716 else
7717 target = curproxy;
7718
7719 if (!target) {
7720 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7721 curproxy->id, mrule->table.name);
7722 cfgerr++;
7723 }
7724 else if (target->table.size == 0) {
7725 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7726 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7727 cfgerr++;
7728 }
Willy Tarreau12785782012-04-27 21:37:17 +02007729 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7730 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007731 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7732 cfgerr++;
7733 }
7734 else {
7735 free((void *)mrule->table.name);
7736 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007737 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007738 }
7739 }
7740
7741 /* find the target table for 'store response' rules */
7742 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7743 struct proxy *target;
7744
Emeric Brun1d33b292010-01-04 15:47:17 +01007745 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 store 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
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007774 /* find the target table for 'tcp-request' layer 4 rules */
7775 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7776 struct proxy *target;
7777
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007778 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007779 continue;
7780
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007781 if (trule->arg.trk_ctr.table.n)
7782 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007783 else
7784 target = curproxy;
7785
7786 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007787 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007788 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007789 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007790 cfgerr++;
7791 }
7792 else if (target->table.size == 0) {
7793 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007794 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007795 cfgerr++;
7796 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007797 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007798 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007799 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007800 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007801 cfgerr++;
7802 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007803 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007804 free(trule->arg.trk_ctr.table.n);
7805 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007806 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007807 * to pass a list of counters to track and allocate them right here using
7808 * stktable_alloc_data_type().
7809 */
7810 }
7811 }
7812
Willy Tarreaud1f96522010-08-03 19:34:32 +02007813 /* find the target table for 'tcp-request' layer 6 rules */
7814 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7815 struct proxy *target;
7816
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007817 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007818 continue;
7819
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007820 if (trule->arg.trk_ctr.table.n)
7821 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007822 else
7823 target = curproxy;
7824
7825 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007826 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007827 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007828 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007829 cfgerr++;
7830 }
7831 else if (target->table.size == 0) {
7832 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007833 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007834 cfgerr++;
7835 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007836 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007837 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007838 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007839 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007840 cfgerr++;
7841 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007842 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007843 free(trule->arg.trk_ctr.table.n);
7844 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007845 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007846 * to pass a list of counters to track and allocate them right here using
7847 * stktable_alloc_data_type().
7848 */
7849 }
7850 }
7851
Baptiste Assmanne9544932015-11-03 23:31:35 +01007852 /* parse http-request capture rules to ensure id really exists */
7853 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7854 if (hrqrule->action != ACT_CUSTOM ||
7855 hrqrule->action_ptr != http_action_req_capture_by_id)
7856 continue;
7857
7858 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7859 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7860 curproxy->id, hrqrule->arg.capid.idx);
7861 cfgerr++;
7862 }
7863 }
7864
7865 /* parse http-response capture rules to ensure id really exists */
7866 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7867 if (hrqrule->action != ACT_CUSTOM ||
7868 hrqrule->action_ptr != http_action_res_capture_by_id)
7869 continue;
7870
7871 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7872 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7873 curproxy->id, hrqrule->arg.capid.idx);
7874 cfgerr++;
7875 }
7876 }
7877
Willy Tarreau09448f72014-06-25 18:12:15 +02007878 /* find the target table for 'http-request' layer 7 rules */
7879 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7880 struct proxy *target;
7881
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007882 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007883 continue;
7884
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007885 if (hrqrule->arg.trk_ctr.table.n)
7886 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007887 else
7888 target = curproxy;
7889
7890 if (!target) {
7891 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007892 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007893 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007894 cfgerr++;
7895 }
7896 else if (target->table.size == 0) {
7897 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007898 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007899 cfgerr++;
7900 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007901 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007902 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007903 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007904 http_trk_idx(hrqrule->action));
7905 cfgerr++;
7906 }
7907 else {
7908 free(hrqrule->arg.trk_ctr.table.n);
7909 hrqrule->arg.trk_ctr.table.t = &target->table;
7910 /* Note: if we decide to enhance the track-sc syntax, we may be able
7911 * to pass a list of counters to track and allocate them right here using
7912 * stktable_alloc_data_type().
7913 */
7914 }
7915 }
7916
7917 /* find the target table for 'http-response' layer 7 rules */
7918 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7919 struct proxy *target;
7920
7921 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7922 continue;
7923
7924 if (hrqrule->arg.trk_ctr.table.n)
7925 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7926 else
7927 target = curproxy;
7928
7929 if (!target) {
7930 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7931 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7932 http_trk_idx(hrqrule->action));
7933 cfgerr++;
7934 }
7935 else if (target->table.size == 0) {
7936 Alert("Proxy '%s': table '%s' used but not configured.\n",
7937 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
7938 cfgerr++;
7939 }
7940 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
7941 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7942 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
7943 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007944 cfgerr++;
7945 }
7946 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007947 free(hrqrule->arg.trk_ctr.table.n);
7948 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007949 /* Note: if we decide to enhance the track-sc syntax, we may be able
7950 * to pass a list of counters to track and allocate them right here using
7951 * stktable_alloc_data_type().
7952 */
7953 }
7954 }
7955
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007956 /* move any "block" rules at the beginning of the http-request rules */
7957 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7958 /* insert block_rules into http_req_rules at the beginning */
7959 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7960 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7961 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7962 curproxy->http_req_rules.n = curproxy->block_rules.n;
7963 LIST_INIT(&curproxy->block_rules);
7964 }
7965
Emeric Brun32da3c42010-09-23 18:39:19 +02007966 if (curproxy->table.peers.name) {
7967 struct peers *curpeers = peers;
7968
7969 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7970 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7971 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007972 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007973 break;
7974 }
7975 }
7976
7977 if (!curpeers) {
7978 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7979 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007980 free((void *)curproxy->table.peers.name);
7981 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007982 cfgerr++;
7983 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007984 else if (curpeers->state == PR_STSTOPPED) {
7985 /* silently disable this peers section */
7986 curproxy->table.peers.p = NULL;
7987 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007988 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007989 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7990 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007991 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007992 cfgerr++;
7993 }
7994 }
7995
Simon Horman9dc49962015-01-30 11:22:59 +09007996
7997 if (curproxy->email_alert.mailers.name) {
7998 struct mailers *curmailers = mailers;
7999
8000 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8001 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8002 free(curproxy->email_alert.mailers.name);
8003 curproxy->email_alert.mailers.m = curmailers;
8004 curmailers->users++;
8005 break;
8006 }
8007 }
8008
8009 if (!curmailers) {
8010 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8011 curproxy->id, curproxy->email_alert.mailers.name);
8012 free_email_alert(curproxy);
8013 cfgerr++;
8014 }
8015 }
8016
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008017 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008018 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008019 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8020 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8021 "proxy", curproxy->id);
8022 cfgerr++;
8023 goto out_uri_auth_compat;
8024 }
8025
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008026 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008027 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008028 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008029 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008030
Willy Tarreau95fa4692010-02-01 13:05:50 +01008031 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8032 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008033
8034 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008035 uri_auth_compat_req[i++] = "realm";
8036 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8037 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008038
Willy Tarreau95fa4692010-02-01 13:05:50 +01008039 uri_auth_compat_req[i++] = "unless";
8040 uri_auth_compat_req[i++] = "{";
8041 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8042 uri_auth_compat_req[i++] = "}";
8043 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008044
Willy Tarreauff011f22011-01-06 17:51:27 +01008045 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8046 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008047 cfgerr++;
8048 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008049 }
8050
Willy Tarreauff011f22011-01-06 17:51:27 +01008051 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008052
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008053 if (curproxy->uri_auth->auth_realm) {
8054 free(curproxy->uri_auth->auth_realm);
8055 curproxy->uri_auth->auth_realm = NULL;
8056 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008057
8058 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008059 }
8060out_uri_auth_compat:
8061
Dragan Dosen43885c72015-10-01 13:18:13 +02008062 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008063 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008064 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8065 if (!curproxy->conf.logformat_sd_string) {
8066 /* set the default logformat_sd_string */
8067 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8068 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008069 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008070 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008071 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008072
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008073 /* compile the log format */
8074 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008075 if (curproxy->conf.logformat_string != default_http_log_format &&
8076 curproxy->conf.logformat_string != default_tcp_log_format &&
8077 curproxy->conf.logformat_string != clf_http_log_format)
8078 free(curproxy->conf.logformat_string);
8079 curproxy->conf.logformat_string = NULL;
8080 free(curproxy->conf.lfs_file);
8081 curproxy->conf.lfs_file = NULL;
8082 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008083
8084 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8085 free(curproxy->conf.logformat_sd_string);
8086 curproxy->conf.logformat_sd_string = NULL;
8087 free(curproxy->conf.lfsd_file);
8088 curproxy->conf.lfsd_file = NULL;
8089 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008090 }
8091
Willy Tarreau62a61232013-04-12 18:13:46 +02008092 if (curproxy->conf.logformat_string) {
8093 curproxy->conf.args.ctx = ARGC_LOG;
8094 curproxy->conf.args.file = curproxy->conf.lfs_file;
8095 curproxy->conf.args.line = curproxy->conf.lfs_line;
8096 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008097 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008098 curproxy->conf.args.file = NULL;
8099 curproxy->conf.args.line = 0;
8100 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008101
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008102 if (curproxy->conf.logformat_sd_string) {
8103 curproxy->conf.args.ctx = ARGC_LOGSD;
8104 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8105 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8106 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8107 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8108 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8109 curproxy->conf.args.file = NULL;
8110 curproxy->conf.args.line = 0;
8111 }
8112
Willy Tarreau62a61232013-04-12 18:13:46 +02008113 if (curproxy->conf.uniqueid_format_string) {
8114 curproxy->conf.args.ctx = ARGC_UIF;
8115 curproxy->conf.args.file = curproxy->conf.uif_file;
8116 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008117 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008118 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008119 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008120 curproxy->conf.args.file = NULL;
8121 curproxy->conf.args.line = 0;
8122 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008123
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008124 /* only now we can check if some args remain unresolved.
8125 * This must be done after the users and groups resolution.
8126 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008127 cfgerr += smp_resolve_args(curproxy);
8128 if (!cfgerr)
8129 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008130
Willy Tarreau2738a142006-07-08 17:28:09 +02008131 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008132 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008133 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008134 (!curproxy->timeout.connect ||
8135 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008136 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008137 " | While not properly invalid, you will certainly encounter various problems\n"
8138 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008139 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008140 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008141 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008142 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008143
Willy Tarreau1fa31262007-12-03 00:36:16 +01008144 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8145 * We must still support older configurations, so let's find out whether those
8146 * parameters have been set or must be copied from contimeouts.
8147 */
8148 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008149 if (!curproxy->timeout.tarpit ||
8150 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008151 /* tarpit timeout not set. We search in the following order:
8152 * default.tarpit, curr.connect, default.connect.
8153 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008154 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008155 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008156 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008157 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008158 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008159 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008160 }
8161 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008162 (!curproxy->timeout.queue ||
8163 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008164 /* queue timeout not set. We search in the following order:
8165 * default.queue, curr.connect, default.connect.
8166 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008167 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008168 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008169 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008170 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008171 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008172 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008173 }
8174 }
8175
Willy Tarreau1620ec32011-08-06 17:05:02 +02008176 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008177 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008178 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008179 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008180 }
8181
Willy Tarreau215663d2014-06-13 18:30:23 +02008182 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8183 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8184 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8185 proxy_type_str(curproxy), curproxy->id);
8186 err_code |= ERR_WARN;
8187 }
8188
Willy Tarreau193b8c62012-11-22 00:17:38 +01008189 /* ensure that cookie capture length is not too large */
8190 if (curproxy->capture_len >= global.tune.cookie_len) {
8191 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8192 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8193 err_code |= ERR_WARN;
8194 curproxy->capture_len = global.tune.cookie_len - 1;
8195 }
8196
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008197 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008198 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008199 curproxy->req_cap_pool = create_pool("ptrcap",
8200 curproxy->nb_req_cap * sizeof(char *),
8201 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008202 }
8203
8204 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008205 curproxy->rsp_cap_pool = create_pool("ptrcap",
8206 curproxy->nb_rsp_cap * sizeof(char *),
8207 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008208 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008209
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008210 switch (curproxy->load_server_state_from_file) {
8211 case PR_SRV_STATE_FILE_UNSPEC:
8212 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8213 break;
8214 case PR_SRV_STATE_FILE_GLOBAL:
8215 if (!global.server_state_file) {
8216 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",
8217 curproxy->id);
8218 err_code |= ERR_WARN;
8219 }
8220 break;
8221 }
8222
Willy Tarreaubaaee002006-06-26 02:48:02 +02008223 /* first, we will invert the servers list order */
8224 newsrv = NULL;
8225 while (curproxy->srv) {
8226 struct server *next;
8227
8228 next = curproxy->srv->next;
8229 curproxy->srv->next = newsrv;
8230 newsrv = curproxy->srv;
8231 if (!next)
8232 break;
8233 curproxy->srv = next;
8234 }
8235
Willy Tarreau17edc812014-01-03 12:14:34 +01008236 /* Check that no server name conflicts. This causes trouble in the stats.
8237 * We only emit a warning for the first conflict affecting each server,
8238 * in order to avoid combinatory explosion if all servers have the same
8239 * name. We do that only for servers which do not have an explicit ID,
8240 * because these IDs were made also for distinguishing them and we don't
8241 * want to annoy people who correctly manage them.
8242 */
8243 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8244 struct server *other_srv;
8245
8246 if (newsrv->puid)
8247 continue;
8248
8249 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8250 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8251 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8252 newsrv->conf.file, newsrv->conf.line,
8253 proxy_type_str(curproxy), curproxy->id,
8254 newsrv->id, other_srv->conf.line);
8255 break;
8256 }
8257 }
8258 }
8259
Willy Tarreaudd701652010-05-25 23:03:02 +02008260 /* assign automatic UIDs to servers which don't have one yet */
8261 next_id = 1;
8262 newsrv = curproxy->srv;
8263 while (newsrv != NULL) {
8264 if (!newsrv->puid) {
8265 /* server ID not set, use automatic numbering with first
8266 * spare entry starting with next_svid.
8267 */
8268 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8269 newsrv->conf.id.key = newsrv->puid = next_id;
8270 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8271 }
8272 next_id++;
8273 newsrv = newsrv->next;
8274 }
8275
Willy Tarreau20697042007-11-15 23:26:18 +01008276 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008277 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008278
Willy Tarreau62c3be22012-01-20 13:12:32 +01008279 /*
8280 * If this server supports a maxconn parameter, it needs a dedicated
8281 * tasks to fill the emptied slots when a connection leaves.
8282 * Also, resolve deferred tracking dependency if needed.
8283 */
8284 newsrv = curproxy->srv;
8285 while (newsrv != NULL) {
8286 if (newsrv->minconn > newsrv->maxconn) {
8287 /* Only 'minconn' was specified, or it was higher than or equal
8288 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8289 * this will avoid further useless expensive computations.
8290 */
8291 newsrv->maxconn = newsrv->minconn;
8292 } else if (newsrv->maxconn && !newsrv->minconn) {
8293 /* minconn was not specified, so we set it to maxconn */
8294 newsrv->minconn = newsrv->maxconn;
8295 }
8296
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008297#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008298 if (newsrv->use_ssl || newsrv->check.use_ssl)
8299 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008300#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008301
Willy Tarreau2f075e92013-12-03 11:11:34 +01008302 /* set the check type on the server */
8303 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8304
Willy Tarreau62c3be22012-01-20 13:12:32 +01008305 if (newsrv->trackit) {
8306 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008307 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008308 char *pname, *sname;
8309
8310 pname = newsrv->trackit;
8311 sname = strrchr(pname, '/');
8312
8313 if (sname)
8314 *sname++ = '\0';
8315 else {
8316 sname = pname;
8317 pname = NULL;
8318 }
8319
8320 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008321 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008322 if (!px) {
8323 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8324 proxy_type_str(curproxy), curproxy->id,
8325 newsrv->id, pname);
8326 cfgerr++;
8327 goto next_srv;
8328 }
8329 } else
8330 px = curproxy;
8331
8332 srv = findserver(px, sname);
8333 if (!srv) {
8334 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8335 proxy_type_str(curproxy), curproxy->id,
8336 newsrv->id, sname);
8337 cfgerr++;
8338 goto next_srv;
8339 }
8340
Willy Tarreau32091232014-05-16 13:52:00 +02008341 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8342 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8343 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008344 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008345 "tracking as it does not have any check nor agent enabled.\n",
8346 proxy_type_str(curproxy), curproxy->id,
8347 newsrv->id, px->id, srv->id);
8348 cfgerr++;
8349 goto next_srv;
8350 }
8351
8352 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8353
8354 if (loop) {
8355 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8356 "belongs to a tracking chain looping back to %s/%s.\n",
8357 proxy_type_str(curproxy), curproxy->id,
8358 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008359 cfgerr++;
8360 goto next_srv;
8361 }
8362
8363 if (curproxy != px &&
8364 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8365 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8366 "tracking: disable-on-404 option inconsistency.\n",
8367 proxy_type_str(curproxy), curproxy->id,
8368 newsrv->id, px->id, srv->id);
8369 cfgerr++;
8370 goto next_srv;
8371 }
8372
8373 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008374 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008375 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008376 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008377 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008378 }
8379
8380 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008381 newsrv->tracknext = srv->trackers;
8382 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008383
8384 free(newsrv->trackit);
8385 newsrv->trackit = NULL;
8386 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008387
8388 /*
8389 * resolve server's resolvers name and update the resolvers pointer
8390 * accordingly
8391 */
8392 if (newsrv->resolvers_id) {
8393 struct dns_resolvers *curr_resolvers;
8394 int found;
8395
8396 found = 0;
8397 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8398 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8399 found = 1;
8400 break;
8401 }
8402 }
8403
8404 if (!found) {
8405 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8406 proxy_type_str(curproxy), curproxy->id,
8407 newsrv->id, newsrv->resolvers_id);
8408 cfgerr++;
8409 } else {
8410 free(newsrv->resolvers_id);
8411 newsrv->resolvers_id = NULL;
8412 if (newsrv->resolution)
8413 newsrv->resolution->resolvers = curr_resolvers;
8414 }
8415 }
8416 else {
8417 /* if no resolvers section associated to this server
8418 * we can clean up the associated resolution structure
8419 */
8420 if (newsrv->resolution) {
8421 free(newsrv->resolution->hostname_dn);
8422 newsrv->resolution->hostname_dn = NULL;
8423 free(newsrv->resolution);
8424 newsrv->resolution = NULL;
8425 }
8426 }
8427
Willy Tarreau62c3be22012-01-20 13:12:32 +01008428 next_srv:
8429 newsrv = newsrv->next;
8430 }
8431
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008432 /* We have to initialize the server lookup mechanism depending
8433 * on what LB algorithm was choosen.
8434 */
8435
8436 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8437 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8438 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008439 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8440 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8441 init_server_map(curproxy);
8442 } else {
8443 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8444 fwrr_init_server_groups(curproxy);
8445 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008446 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008447
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008448 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008449 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8450 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8451 fwlc_init_server_tree(curproxy);
8452 } else {
8453 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8454 fas_init_server_tree(curproxy);
8455 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008456 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008457
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008458 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008459 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8460 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8461 chash_init_server_tree(curproxy);
8462 } else {
8463 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8464 init_server_map(curproxy);
8465 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008466 break;
8467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008468
8469 if (curproxy->options & PR_O_LOGASAP)
8470 curproxy->to_log &= ~LW_BYTES;
8471
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008472 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008473 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8474 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008475 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8476 proxy_type_str(curproxy), curproxy->id);
8477 err_code |= ERR_WARN;
8478 }
8479
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008480 if (curproxy->mode != PR_MODE_HTTP) {
8481 int optnum;
8482
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008483 if (curproxy->uri_auth) {
8484 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8485 proxy_type_str(curproxy), curproxy->id);
8486 err_code |= ERR_WARN;
8487 curproxy->uri_auth = NULL;
8488 }
8489
Willy Tarreau87cf5142011-08-19 22:57:24 +02008490 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008491 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8492 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8493 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008494 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008495 }
8496
8497 if (curproxy->options & PR_O_ORGTO) {
8498 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8499 "originalto", proxy_type_str(curproxy), curproxy->id);
8500 err_code |= ERR_WARN;
8501 curproxy->options &= ~PR_O_ORGTO;
8502 }
8503
8504 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8505 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8506 (curproxy->cap & cfg_opts[optnum].cap) &&
8507 (curproxy->options & cfg_opts[optnum].val)) {
8508 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8509 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8510 err_code |= ERR_WARN;
8511 curproxy->options &= ~cfg_opts[optnum].val;
8512 }
8513 }
8514
8515 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8516 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8517 (curproxy->cap & cfg_opts2[optnum].cap) &&
8518 (curproxy->options2 & cfg_opts2[optnum].val)) {
8519 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8520 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8521 err_code |= ERR_WARN;
8522 curproxy->options2 &= ~cfg_opts2[optnum].val;
8523 }
8524 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008525
Willy Tarreau29fbe512015-08-20 19:35:14 +02008526#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008527 if (curproxy->conn_src.bind_hdr_occ) {
8528 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008529 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008530 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008531 err_code |= ERR_WARN;
8532 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008533#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008534 }
8535
Willy Tarreaubaaee002006-06-26 02:48:02 +02008536 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008537 * ensure that we're not cross-dressing a TCP server into HTTP.
8538 */
8539 newsrv = curproxy->srv;
8540 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008541 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008542 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8543 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008544 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008545 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008546
Willy Tarreau0cec3312011-10-31 13:49:26 +01008547 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8548 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8549 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8550 err_code |= ERR_WARN;
8551 }
8552
Willy Tarreauc93cd162014-05-13 15:54:22 +02008553 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008554 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8555 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8556 err_code |= ERR_WARN;
8557 }
8558
Willy Tarreau29fbe512015-08-20 19:35:14 +02008559#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008560 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8561 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008562 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 +01008563 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008564 err_code |= ERR_WARN;
8565 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008566#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008567 newsrv = newsrv->next;
8568 }
8569
Willy Tarreaue42bd962014-09-16 16:21:19 +02008570 /* check if we have a frontend with "tcp-request content" looking at L7
8571 * with no inspect-delay
8572 */
8573 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8574 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008575 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008576 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008577 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008578 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008579 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008580 break;
8581 }
8582
8583 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8584 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8585 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8586 " This means that these rules will randomly find their contents. This can be fixed by"
8587 " setting the tcp-request inspect-delay.\n",
8588 proxy_type_str(curproxy), curproxy->id);
8589 err_code |= ERR_WARN;
8590 }
8591 }
8592
Christopher Fauletd7c91962015-04-30 11:48:27 +02008593 /* Check filter configuration, if any */
8594 cfgerr += flt_check(curproxy);
8595
Willy Tarreauc1a21672009-08-16 22:37:44 +02008596 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008597 if (!curproxy->accept)
8598 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008599
Willy Tarreauc1a21672009-08-16 22:37:44 +02008600 if (curproxy->tcp_req.inspect_delay ||
8601 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008602 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008603
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008604 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008605 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008606 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008607 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008608
8609 /* both TCP and HTTP must check switching rules */
8610 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008611
8612 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008613 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008614 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8615 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008616 if (curproxy->mode == PR_MODE_HTTP) {
8617 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8618 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8619 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008620 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008621 }
8622
8623 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008624 if (curproxy->tcp_req.inspect_delay ||
8625 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8626 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8627
Emeric Brun97679e72010-09-23 17:56:44 +02008628 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8629 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8630
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008631 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008632 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008633 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008634 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008635
8636 /* If the backend does requires RDP cookie persistence, we have to
8637 * enable the corresponding analyser.
8638 */
8639 if (curproxy->options2 & PR_O2_RDPC_PRST)
8640 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008641
8642 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008643 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008644 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8645 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008646 if (curproxy->mode == PR_MODE_HTTP) {
8647 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8648 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8649 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008650 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008651 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008652 }
8653
8654 /***********************************************************/
8655 /* At this point, target names have already been resolved. */
8656 /***********************************************************/
8657
8658 /* Check multi-process mode compatibility */
8659
8660 if (global.nbproc > 1 && global.stats_fe) {
8661 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8662 unsigned long mask;
8663
8664 mask = nbits(global.nbproc);
8665 if (global.stats_fe->bind_proc)
8666 mask &= global.stats_fe->bind_proc;
8667
8668 if (bind_conf->bind_proc)
8669 mask &= bind_conf->bind_proc;
8670
8671 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008672 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008673 break;
8674 }
8675 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8676 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");
8677 }
8678 }
8679
8680 /* Make each frontend inherit bind-process from its listeners when not specified. */
8681 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8682 if (curproxy->bind_proc)
8683 continue;
8684
8685 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8686 unsigned long mask;
8687
Willy Tarreaue428b082015-05-04 21:57:58 +02008688 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008689 curproxy->bind_proc |= mask;
8690 }
8691
8692 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008693 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008694 }
8695
8696 if (global.stats_fe) {
8697 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8698 unsigned long mask;
8699
Cyril Bonté06181952016-02-24 00:14:54 +01008700 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008701 global.stats_fe->bind_proc |= mask;
8702 }
8703 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008704 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008705 }
8706
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008707 /* propagate bindings from frontends to backends. Don't do it if there
8708 * are any fatal errors as we must not call it with unresolved proxies.
8709 */
8710 if (!cfgerr) {
8711 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8712 if (curproxy->cap & PR_CAP_FE)
8713 propagate_processes(curproxy, NULL);
8714 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008715 }
8716
8717 /* Bind each unbound backend to all processes when not specified. */
8718 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8719 if (curproxy->bind_proc)
8720 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008721 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008722 }
8723
8724 /*******************************************************/
8725 /* At this step, all proxies have a non-null bind_proc */
8726 /*******************************************************/
8727
8728 /* perform the final checks before creating tasks */
8729
8730 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8731 struct listener *listener;
8732 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008733
Emeric Brunc52962f2012-11-15 18:28:02 +01008734#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008735 /* Configure SSL for each bind line.
8736 * Note: if configuration fails at some point, the ->ctx member
8737 * remains NULL so that listeners can later detach.
8738 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008739 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008740 int alloc_ctx;
8741
Emeric Brunc52962f2012-11-15 18:28:02 +01008742 if (!bind_conf->is_ssl) {
8743 if (bind_conf->default_ctx) {
8744 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8745 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8746 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008747 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008748 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008749 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008750 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008751 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008752 cfgerr++;
8753 continue;
8754 }
8755
Emeric Brun8dc60392014-05-09 13:52:00 +02008756 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008757 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008758 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8759 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");
8760 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008761 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008762 cfgerr++;
8763 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008764 }
8765
Emeric Brunfc0421f2012-09-07 17:30:07 +02008766 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008767 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008768
8769 /* initialize CA variables if the certificates generation is enabled */
8770 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008771 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008772#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008773
Willy Tarreaue6b98942007-10-29 01:09:36 +01008774 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008775 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008776 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008777 int nbproc;
8778
8779 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008780 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008781 nbits(global.nbproc));
8782
8783 if (!nbproc) /* no intersection between listener and frontend */
8784 nbproc = 1;
8785
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008786 if (!listener->luid) {
8787 /* listener ID not set, use automatic numbering with first
8788 * spare entry starting with next_luid.
8789 */
8790 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8791 listener->conf.id.key = listener->luid = next_id;
8792 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008793 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008794 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008795
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008796 /* enable separate counters */
8797 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008798 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008799 if (!listener->name)
8800 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008801 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008802
Willy Tarreaue6b98942007-10-29 01:09:36 +01008803 if (curproxy->options & PR_O_TCP_NOLING)
8804 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008805 if (!listener->maxconn)
8806 listener->maxconn = curproxy->maxconn;
8807 if (!listener->backlog)
8808 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008809 if (!listener->maxaccept)
8810 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8811
8812 /* we want to have an optimal behaviour on single process mode to
8813 * maximize the work at once, but in multi-process we want to keep
8814 * some fairness between processes, so we target half of the max
8815 * number of events to be balanced over all the processes the proxy
8816 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8817 * used to disable the limit.
8818 */
8819 if (listener->maxaccept > 0) {
8820 if (nbproc > 1)
8821 listener->maxaccept = (listener->maxaccept + 1) / 2;
8822 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8823 }
8824
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008825 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008826 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008827 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008828 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008829
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008830 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008831 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008832
Willy Tarreaude3041d2010-05-31 10:56:17 +02008833 if (curproxy->mon_mask.s_addr)
8834 listener->options |= LI_O_CHK_MONNET;
8835
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008836 /* smart accept mode is automatic in HTTP mode */
8837 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008838 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008839 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8840 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008841 }
8842
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008843 /* Release unused SSL configs */
8844 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8845 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008846 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008847#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008848 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008849 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008850 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008851 free(bind_conf->ca_sign_file);
8852 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008853 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008854 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008855 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008856 if(bind_conf->keys_ref) {
8857 free(bind_conf->keys_ref->filename);
8858 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02008859 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008860 free(bind_conf->keys_ref);
8861 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008862#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008863 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008864
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008865 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008866 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008867 int count, maxproc = 0;
8868
8869 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008870 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008871 if (count > maxproc)
8872 maxproc = count;
8873 }
8874 /* backends have 0, frontends have 1 or more */
8875 if (maxproc != 1)
8876 Warning("Proxy '%s': in multi-process mode, stats will be"
8877 " limited to process assigned to the current request.\n",
8878 curproxy->id);
8879
Willy Tarreau102df612014-05-07 23:56:38 +02008880 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8881 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8882 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008883 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008884 }
Willy Tarreau102df612014-05-07 23:56:38 +02008885 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8886 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8887 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008888 }
8889 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008890
8891 /* create the task associated with the proxy */
8892 curproxy->task = task_new();
8893 if (curproxy->task) {
8894 curproxy->task->context = curproxy;
8895 curproxy->task->process = manage_proxy;
8896 /* no need to queue, it will be done automatically if some
8897 * listener gets limited.
8898 */
8899 curproxy->task->expire = TICK_ETERNITY;
8900 } else {
8901 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8902 curproxy->id);
8903 cfgerr++;
8904 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008905 }
8906
Willy Tarreaufbb78422011-06-05 15:38:35 +02008907 /* automatically compute fullconn if not set. We must not do it in the
8908 * loop above because cross-references are not yet fully resolved.
8909 */
8910 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8911 /* If <fullconn> is not set, let's set it to 10% of the sum of
8912 * the possible incoming frontend's maxconns.
8913 */
8914 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8915 struct proxy *fe;
8916 int total = 0;
8917
8918 /* sum up the number of maxconns of frontends which
8919 * reference this backend at least once or which are
8920 * the same one ('listen').
8921 */
8922 for (fe = proxy; fe; fe = fe->next) {
8923 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008924 int found = 0;
8925
8926 if (!(fe->cap & PR_CAP_FE))
8927 continue;
8928
8929 if (fe == curproxy) /* we're on a "listen" instance */
8930 found = 1;
8931
8932 if (fe->defbe.be == curproxy) /* "default_backend" */
8933 found = 1;
8934
8935 /* check if a "use_backend" rule matches */
8936 if (!found) {
8937 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008938 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008939 found = 1;
8940 break;
8941 }
8942 }
8943 }
8944
Willy Tarreaufbb78422011-06-05 15:38:35 +02008945 /* now we've checked all possible ways to reference a backend
8946 * from a frontend.
8947 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008948 if (!found)
8949 continue;
8950 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008951 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008952 /* we have the sum of the maxconns in <total>. We only
8953 * keep 10% of that sum to set the default fullconn, with
8954 * a hard minimum of 1 (to avoid a divide by zero).
8955 */
8956 curproxy->fullconn = (total + 9) / 10;
8957 if (!curproxy->fullconn)
8958 curproxy->fullconn = 1;
8959 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008960 }
8961
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008962 /*
8963 * Recount currently required checks.
8964 */
8965
8966 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8967 int optnum;
8968
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008969 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8970 if (curproxy->options & cfg_opts[optnum].val)
8971 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008972
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008973 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8974 if (curproxy->options2 & cfg_opts2[optnum].val)
8975 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008976 }
8977
Willy Tarreau0fca4832015-05-01 19:12:05 +02008978 /* compute the required process bindings for the peers */
8979 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8980 if (curproxy->table.peers.p)
8981 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8982
Willy Tarreau122541c2011-09-07 21:24:49 +02008983 if (peers) {
8984 struct peers *curpeers = peers, **last;
8985 struct peer *p, *pb;
8986
Willy Tarreau1e273012015-05-01 19:15:17 +02008987 /* Remove all peers sections which don't have a valid listener,
8988 * which are not used by any table, or which are bound to more
8989 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008990 */
8991 last = &peers;
8992 while (*last) {
8993 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008994
8995 if (curpeers->state == PR_STSTOPPED) {
8996 /* the "disabled" keyword was present */
8997 if (curpeers->peers_fe)
8998 stop_proxy(curpeers->peers_fe);
8999 curpeers->peers_fe = NULL;
9000 }
9001 else if (!curpeers->peers_fe) {
9002 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9003 curpeers->id, localpeer);
9004 }
David Carliere6c39412015-07-02 07:00:17 +00009005 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009006 /* either it's totally stopped or too much used */
9007 if (curpeers->peers_fe->bind_proc) {
9008 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009009 "running in different processes (%d different ones). "
9010 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009011 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009012 cfgerr++;
9013 }
9014 stop_proxy(curpeers->peers_fe);
9015 curpeers->peers_fe = NULL;
9016 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009017 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009018 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009019 last = &curpeers->next;
9020 continue;
9021 }
9022
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009023 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009024 p = curpeers->remote;
9025 while (p) {
9026 pb = p->next;
9027 free(p->id);
9028 free(p);
9029 p = pb;
9030 }
9031
9032 /* Destroy and unlink this curpeers section.
9033 * Note: curpeers is backed up into *last.
9034 */
9035 free(curpeers->id);
9036 curpeers = curpeers->next;
9037 free(*last);
9038 *last = curpeers;
9039 }
9040 }
9041
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009042 /* initialize stick-tables on backend capable proxies. This must not
9043 * be done earlier because the data size may be discovered while parsing
9044 * other proxies.
9045 */
9046 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9047 if (curproxy->state == PR_STSTOPPED)
9048 continue;
9049
9050 if (!stktable_init(&curproxy->table)) {
9051 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9052 cfgerr++;
9053 }
9054 }
9055
Simon Horman0d16a402015-01-30 11:22:58 +09009056 if (mailers) {
9057 struct mailers *curmailers = mailers, **last;
9058 struct mailer *m, *mb;
9059
9060 /* Remove all mailers sections which don't have a valid listener.
9061 * This can happen when a mailers section is never referenced.
9062 */
9063 last = &mailers;
9064 while (*last) {
9065 curmailers = *last;
9066 if (curmailers->users) {
9067 last = &curmailers->next;
9068 continue;
9069 }
9070
9071 Warning("Removing incomplete section 'mailers %s'.\n",
9072 curmailers->id);
9073
9074 m = curmailers->mailer_list;
9075 while (m) {
9076 mb = m->next;
9077 free(m->id);
9078 free(m);
9079 m = mb;
9080 }
9081
9082 /* Destroy and unlink this curmailers section.
9083 * Note: curmailers is backed up into *last.
9084 */
9085 free(curmailers->id);
9086 curmailers = curmailers->next;
9087 free(*last);
9088 *last = curmailers;
9089 }
9090 }
9091
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009092 /* Update server_state_file_name to backend name if backend is supposed to use
9093 * a server-state file locally defined and none has been provided */
9094 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9095 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9096 curproxy->server_state_file_name == NULL)
9097 curproxy->server_state_file_name = strdup(curproxy->id);
9098 }
9099
Willy Tarreau34eb6712011-10-24 18:15:04 +02009100 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009101 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009102 MEM_F_SHARED);
9103
Willy Tarreaubb925012009-07-23 13:36:36 +02009104 if (cfgerr > 0)
9105 err_code |= ERR_ALERT | ERR_FATAL;
9106 out:
9107 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009108}
9109
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009110/*
9111 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9112 * parsing sessions.
9113 */
9114void cfg_register_keywords(struct cfg_kw_list *kwl)
9115{
9116 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9117}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009118
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009119/*
9120 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9121 */
9122void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9123{
9124 LIST_DEL(&kwl->list);
9125 LIST_INIT(&kwl->list);
9126}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009127
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009128/* this function register new section in the haproxy configuration file.
9129 * <section_name> is the name of this new section and <section_parser>
9130 * is the called parser. If two section declaration have the same name,
9131 * only the first declared is used.
9132 */
9133int cfg_register_section(char *section_name,
9134 int (*section_parser)(const char *, int, char **, int))
9135{
9136 struct cfg_section *cs;
9137
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009138 list_for_each_entry(cs, &sections, list) {
9139 if (strcmp(cs->section_name, section_name) == 0) {
9140 Alert("register section '%s': already registered.\n", section_name);
9141 return 0;
9142 }
9143 }
9144
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009145 cs = calloc(1, sizeof(*cs));
9146 if (!cs) {
9147 Alert("register section '%s': out of memory.\n", section_name);
9148 return 0;
9149 }
9150
9151 cs->section_name = section_name;
9152 cs->section_parser = section_parser;
9153
9154 LIST_ADDQ(&sections, &cs->list);
9155
9156 return 1;
9157}
9158
Willy Tarreaubaaee002006-06-26 02:48:02 +02009159/*
David Carlier845efb52015-09-25 11:49:18 +01009160 * free all config section entries
9161 */
9162void cfg_unregister_sections(void)
9163{
9164 struct cfg_section *cs, *ics;
9165
9166 list_for_each_entry_safe(cs, ics, &sections, list) {
9167 LIST_DEL(&cs->list);
9168 free(cs);
9169 }
9170}
9171
Willy Tarreau659fbf02016-05-26 17:55:28 +02009172__attribute__((constructor))
9173static void cfgparse_init(void)
9174{
9175 /* Register internal sections */
9176 cfg_register_section("listen", cfg_parse_listen);
9177 cfg_register_section("frontend", cfg_parse_listen);
9178 cfg_register_section("backend", cfg_parse_listen);
9179 cfg_register_section("defaults", cfg_parse_listen);
9180 cfg_register_section("global", cfg_parse_global);
9181 cfg_register_section("userlist", cfg_parse_users);
9182 cfg_register_section("peers", cfg_parse_peers);
9183 cfg_register_section("mailers", cfg_parse_mailers);
9184 cfg_register_section("namespace_list", cfg_parse_netns);
9185 cfg_register_section("resolvers", cfg_parse_resolvers);
9186}
9187
David Carlier845efb52015-09-25 11:49:18 +01009188/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009189 * Local variables:
9190 * c-indent-level: 8
9191 * c-basic-offset: 8
9192 * End:
9193 */