blob: 4923d8609478d1cc23339df43381602f67264304 [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 Tarreau620408f2016-10-21 16:37:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request session' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200374/* Report a warning if a rule is placed after a 'tcp-request content' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
377int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
378{
379 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau61d18892009-03-31 10:49:21 +0200387/* Report a warning if a rule is placed after a 'block' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200392 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200393 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau5002f572014-04-23 01:32:02 +0200400/* Report a warning if a rule is placed after an 'http_request' rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
403int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
404{
405 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
Willy Tarreau61d18892009-03-31 10:49:21 +0200413/* Report a warning if a rule is placed after a reqrewrite rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
418 if (proxy->req_exp) {
419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' 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 reqadd rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100431 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' 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 redirect rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
452/* Report a warning if a rule is placed after a 'use_backend' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100455int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200456{
457 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreauee445d92014-04-23 01:39:04 +0200465/* Report a warning if a rule is placed after a 'use-server' rule.
466 * Return 1 if the warning has been emitted, otherwise 0.
467 */
468int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
469{
470 if (!LIST_ISEMPTY(&proxy->server_rules)) {
471 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
472 file, line, arg);
473 return 1;
474 }
475 return 0;
476}
477
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200478/* report a warning if a "tcp request connection" rule is dangerously placed */
479int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
480{
Willy Tarreau620408f2016-10-21 16:37:51 +0200481 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
482 warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
483 warnif_rule_after_block(proxy, file, line, arg) ||
484 warnif_rule_after_http_req(proxy, file, line, arg) ||
485 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
486 warnif_rule_after_reqadd(proxy, file, line, arg) ||
487 warnif_rule_after_redirect(proxy, file, line, arg) ||
488 warnif_rule_after_use_backend(proxy, file, line, arg) ||
489 warnif_rule_after_use_server(proxy, file, line, arg);
490}
491
492int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
493{
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200494 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
495 warnif_rule_after_block(proxy, file, line, arg) ||
496 warnif_rule_after_http_req(proxy, file, line, arg) ||
497 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
498 warnif_rule_after_reqadd(proxy, file, line, arg) ||
499 warnif_rule_after_redirect(proxy, file, line, arg) ||
500 warnif_rule_after_use_backend(proxy, file, line, arg) ||
501 warnif_rule_after_use_server(proxy, file, line, arg);
502}
503
504/* report a warning if a "tcp request content" rule is dangerously placed */
505int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
506{
507 return warnif_rule_after_block(proxy, file, line, arg) ||
508 warnif_rule_after_http_req(proxy, file, line, arg) ||
509 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
510 warnif_rule_after_reqadd(proxy, file, line, arg) ||
511 warnif_rule_after_redirect(proxy, file, line, arg) ||
512 warnif_rule_after_use_backend(proxy, file, line, arg) ||
513 warnif_rule_after_use_server(proxy, file, line, arg);
514}
515
Willy Tarreau61d18892009-03-31 10:49:21 +0200516/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100517int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200518{
Willy Tarreau5002f572014-04-23 01:32:02 +0200519 return warnif_rule_after_http_req(proxy, file, line, arg) ||
520 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
521 warnif_rule_after_reqadd(proxy, file, line, arg) ||
522 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200523 warnif_rule_after_use_backend(proxy, file, line, arg) ||
524 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200525}
526
527/* report a warning if an http-request rule is dangerously placed */
528int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
529{
Willy Tarreau61d18892009-03-31 10:49:21 +0200530 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
531 warnif_rule_after_reqadd(proxy, file, line, arg) ||
532 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200533 warnif_rule_after_use_backend(proxy, file, line, arg) ||
534 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200535}
536
537/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100538int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200539{
540 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
541 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200542 warnif_rule_after_use_backend(proxy, file, line, arg) ||
543 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200544}
545
546/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100547int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200548{
549 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200550 warnif_rule_after_use_backend(proxy, file, line, arg) ||
551 warnif_rule_after_use_server(proxy, file, line, arg);
552}
553
554/* report a warning if a redirect rule is dangerously placed */
555int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
556{
557 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
558 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200559}
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561/* Report it if a request ACL condition uses some keywords that are incompatible
562 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
563 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
564 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200569 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100570
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100571 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 return 0;
573
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100574 acl = acl_cond_conflicts(cond, where);
575 if (acl) {
576 if (acl->name && *acl->name)
577 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
578 file, line, acl->name, sample_ckp_names(where));
579 else
580 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 +0200581 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 return ERR_WARN;
583 }
584 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100585 return 0;
586
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100587 if (acl->name && *acl->name)
588 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200589 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100590 else
591 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200592 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100593 return ERR_WARN;
594}
595
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200597 * parse a line in a <global> section. Returns the error code, 0 if OK, or
598 * any combination of :
599 * - ERR_ABORT: must abort ASAP
600 * - ERR_FATAL: we can continue parsing but not start the service
601 * - ERR_WARN: a warning has been emitted
602 * - ERR_ALERT: an alert has been emitted
603 * Only the two first ones can stop processing, the two others are just
604 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200606int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607{
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200609 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610
611 if (!strcmp(args[0], "global")) { /* new section */
612 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200613 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200616 else if (!strcmp(args[0], "ca-base")) {
617#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200618 if(alertif_too_many_args(1, file, linenum, args, &err_code))
619 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200620 if (global.ca_base != NULL) {
621 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT;
623 goto out;
624 }
625 if (*(args[1]) == 0) {
626 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT | ERR_FATAL;
628 goto out;
629 }
630 global.ca_base = strdup(args[1]);
631#else
632 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
635#endif
636 }
637 else if (!strcmp(args[0], "crt-base")) {
638#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(1, file, linenum, args, &err_code))
640 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200641 if (global.crt_base != NULL) {
642 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT;
644 goto out;
645 }
646 if (*(args[1]) == 0) {
647 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
648 err_code |= ERR_ALERT | ERR_FATAL;
649 goto out;
650 }
651 global.crt_base = strdup(args[1]);
652#else
653 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656#endif
657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 global.mode |= MODE_DAEMON;
662 }
663 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 global.mode |= MODE_DEBUG;
667 }
668 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(0, file, linenum, args, &err_code))
670 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100671 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200673 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200674 if (alertif_too_many_args(0, file, linenum, args, &err_code))
675 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100676 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200679 if (alertif_too_many_args(0, file, linenum, args, &err_code))
680 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100681 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100683 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200684 if (alertif_too_many_args(0, file, linenum, args, &err_code))
685 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100686 global.tune.options &= ~GTUNE_USE_SPLICE;
687 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200688 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200689 if (alertif_too_many_args(0, file, linenum, args, &err_code))
690 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200691 global.tune.options &= ~GTUNE_USE_GAI;
692 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000693 else if (!strcmp(args[0], "noreuseport")) {
694 if (alertif_too_many_args(0, file, linenum, args, &err_code))
695 goto out;
696 global.tune.options &= ~GTUNE_USE_REUSEPORT;
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200699 if (alertif_too_many_args(0, file, linenum, args, &err_code))
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 global.mode |= MODE_QUIET;
702 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200703 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
705 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200706 if (global.tune.maxpollevents != 0) {
707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 err_code |= ERR_ALERT;
709 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200710 }
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200715 }
716 global.tune.maxpollevents = atol(args[1]);
717 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100718 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
720 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100721 if (global.tune.maxaccept != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT;
724 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100730 }
731 global.tune.maxaccept = atol(args[1]);
732 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200733 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +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.chksize = atol(args[1]);
742 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100743 else if (!strcmp(args[0], "tune.recv_enough")) {
744 if (alertif_too_many_args(1, file, linenum, args, &err_code))
745 goto out;
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 global.tune.recv_enough = atol(args[1]);
752 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200753#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200754 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200755 if (alertif_too_many_args(0, file, linenum, args, &err_code))
756 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200757 global.tune.sslprivatecache = 1;
758 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100759 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.sslcachesize = atol(args[1]);
768 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100769 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
770 unsigned int ssllifetime;
771 const char *res;
772
William Lallemand1a748ae2015-05-19 16:37:23 +0200773 if (alertif_too_many_args(1, file, linenum, args, &err_code))
774 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100775 if (*(args[1]) == 0) {
776 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT | ERR_FATAL;
778 goto out;
779 }
780
781 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
782 if (res) {
783 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
784 file, linenum, *res, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788
789 global.tune.ssllifetime = ssllifetime;
790 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100791 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200792 if (alertif_too_many_args(1, file, linenum, args, &err_code))
793 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.ssl_max_record = atol(args[1]);
800 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200801#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200802 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200803 if (alertif_too_many_args(1, file, linenum, args, &err_code))
804 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.ssl_default_dh_param = atol(args[1]);
811 if (global.tune.ssl_default_dh_param < 1024) {
812 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200817#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200818 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
820 goto out;
821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.tune.ssl_ctx_cache = atoi(args[1]);
827 if (global.tune.ssl_ctx_cache < 0) {
828 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
829 file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200834#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100835 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100838 if (*(args[1]) == 0) {
839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 global.tune.buf_limit = atol(args[1]);
844 if (global.tune.buf_limit) {
845 if (global.tune.buf_limit < 3)
846 global.tune.buf_limit = 3;
847 if (global.tune.buf_limit <= global.tune.reserved_bufs)
848 global.tune.buf_limit = global.tune.reserved_bufs + 1;
849 }
850 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100851 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 global.tune.reserved_bufs = atol(args[1]);
860 if (global.tune.reserved_bufs < 2)
861 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100862 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
863 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200866 if (alertif_too_many_args(1, file, linenum, args, &err_code))
867 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200868 if (*(args[1]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200874 if (global.tune.bufsize <= 0) {
875 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100879 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100880 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200881 }
882 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200883 if (alertif_too_many_args(1, file, linenum, args, &err_code))
884 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200891 if (global.tune.maxrewrite < 0) {
892 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200896 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100897 else if (!strcmp(args[0], "tune.idletimer")) {
898 unsigned int idle;
899 const char *res;
900
William Lallemand1a748ae2015-05-19 16:37:23 +0200901 if (alertif_too_many_args(1, file, linenum, args, &err_code))
902 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908
909 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
910 if (res) {
911 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
912 file, linenum, *res, args[0]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
916
917 if (idle > 65535) {
918 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 global.tune.idle_timer = idle;
923 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100924 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200925 if (alertif_too_many_args(1, file, linenum, args, &err_code))
926 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100927 if (global.tune.client_rcvbuf != 0) {
928 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
929 err_code |= ERR_ALERT;
930 goto out;
931 }
932 if (*(args[1]) == 0) {
933 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 global.tune.client_rcvbuf = atol(args[1]);
938 }
939 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200940 if (alertif_too_many_args(1, file, linenum, args, &err_code))
941 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100942 if (global.tune.server_rcvbuf != 0) {
943 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
944 err_code |= ERR_ALERT;
945 goto out;
946 }
947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 global.tune.server_rcvbuf = atol(args[1]);
953 }
954 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200955 if (alertif_too_many_args(1, file, linenum, args, &err_code))
956 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100957 if (global.tune.client_sndbuf != 0) {
958 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
959 err_code |= ERR_ALERT;
960 goto out;
961 }
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 global.tune.client_sndbuf = atol(args[1]);
968 }
969 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200970 if (alertif_too_many_args(1, file, linenum, args, &err_code))
971 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100972 if (global.tune.server_sndbuf != 0) {
973 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT;
975 goto out;
976 }
977 if (*(args[1]) == 0) {
978 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981 }
982 global.tune.server_sndbuf = atol(args[1]);
983 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200984 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
986 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200987 if (*(args[1]) == 0) {
988 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
991 }
992 global.tune.pipesize = atol(args[1]);
993 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100994 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200995 if (alertif_too_many_args(1, file, linenum, args, &err_code))
996 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 global.tune.cookie_len = atol(args[1]) + 1;
1003 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001004 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001005 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1006 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +02001007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 global.tune.max_http_hdr = atol(args[1]);
1013 }
William Lallemanda509e4c2012-11-07 16:54:34 +01001014 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
1015#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001016 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1017 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001018 if (*args[1]) {
1019 global.tune.zlibmemlevel = atoi(args[1]);
1020 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
1021 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 } else {
1027 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1028 file, linenum, args[0]);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031 }
1032#else
1033 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036#endif
1037 }
1038 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1039#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001040 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1041 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001042 if (*args[1]) {
1043 global.tune.zlibwindowsize = atoi(args[1]);
1044 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1045 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1046 file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050 } else {
1051 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1052 file, linenum, args[0]);
1053 err_code |= ERR_ALERT | ERR_FATAL;
1054 goto out;
1055 }
1056#else
1057 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060#endif
1061 }
William Lallemandf3747832012-11-09 12:33:10 +01001062 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001063 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1064 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001065 if (*args[1]) {
1066 global.tune.comp_maxlevel = atoi(args[1]);
1067 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1068 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1069 file, linenum, args[0]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073 } else {
1074 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1075 file, linenum, args[0]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001080 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1081 if (*args[1]) {
1082 global.tune.pattern_cache = atoi(args[1]);
1083 if (global.tune.pattern_cache < 0) {
1084 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1085 file, linenum, args[0]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089 } else {
1090 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1091 file, linenum, args[0]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001097 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001101 err_code |= ERR_ALERT;
1102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
1104 if (*(args[1]) == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001109 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1110 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]);
1111 err_code |= ERR_WARN;
1112 goto out;
1113 }
1114
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115 }
1116 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001120 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001121 err_code |= ERR_ALERT;
1122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 }
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001129 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1130 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]);
1131 err_code |= ERR_WARN;
1132 goto out;
1133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 }
Simon Horman98637e52014-06-20 12:30:16 +09001135 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001136 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1137 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001138 global.external_check = 1;
1139 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001140 /* user/group name handling */
1141 else if (!strcmp(args[0], "user")) {
1142 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001143 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1144 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001145 if (global.uid != 0) {
1146 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT;
1148 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001149 }
1150 errno = 0;
1151 ha_user = getpwnam(args[1]);
1152 if (ha_user != NULL) {
1153 global.uid = (int)ha_user->pw_uid;
1154 }
1155 else {
1156 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 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001158 }
1159 }
1160 else if (!strcmp(args[0], "group")) {
1161 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001162 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1163 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001164 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001165 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT;
1167 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001168 }
1169 errno = 0;
1170 ha_group = getgrnam(args[1]);
1171 if (ha_group != NULL) {
1172 global.gid = (int)ha_group->gr_gid;
1173 }
1174 else {
1175 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 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001177 }
1178 }
1179 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001181 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 if (*(args[1]) == 0) {
1184 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 }
1188 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001189 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1190 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1191 file, linenum, args[0], LONGBITS, global.nbproc);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 }
1196 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001197 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 if (global.maxconn != 0) {
1200 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 }
1209 global.maxconn = atol(args[1]);
1210#ifdef SYSTEM_MAXCONN
1211 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1212 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);
1213 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001214 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 }
1216#endif /* SYSTEM_MAXCONN */
1217 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001218 else if (!strcmp(args[0], "maxsslconn")) {
1219#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001220 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1221 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001222 if (*(args[1]) == 0) {
1223 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227 global.maxsslconn = atol(args[1]);
1228#else
Emeric Brun0914df82012-10-02 18:45:42 +02001229 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001232#endif
1233 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001234 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1235#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001236 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1237 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001238 if (*(args[1]) == 0) {
1239 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243 free(global.listen_default_ciphers);
1244 global.listen_default_ciphers = strdup(args[1]);
1245#else
1246 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249#endif
1250 }
1251 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1252#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001253 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1254 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001255 if (*(args[1]) == 0) {
1256 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260 free(global.connect_default_ciphers);
1261 global.connect_default_ciphers = strdup(args[1]);
1262#else
1263 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto out;
1266#endif
1267 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001268#ifdef USE_OPENSSL
1269#ifndef OPENSSL_NO_DH
1270 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1271 if (*(args[1]) == 0) {
1272 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
1275 }
1276 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1277 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
1281 }
1282#endif
1283#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001284 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001285 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1286 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001287 if (*(args[1]) == 0) {
1288 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1289 err_code |= ERR_ALERT | ERR_FATAL;
1290 goto out;
1291 }
1292 if (strcmp(args[1],"none") == 0)
1293 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1294 else if (strcmp(args[1],"required") == 0)
1295 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1296 else {
1297 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001302 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001303 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1304 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001305 if (global.cps_lim != 0) {
1306 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1307 err_code |= ERR_ALERT;
1308 goto out;
1309 }
1310 if (*(args[1]) == 0) {
1311 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 global.cps_lim = atol(args[1]);
1316 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001317 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001318 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1319 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001320 if (global.sps_lim != 0) {
1321 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1322 err_code |= ERR_ALERT;
1323 goto out;
1324 }
1325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
1329 }
1330 global.sps_lim = atol(args[1]);
1331 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001332 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001333 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1334 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001335 if (global.ssl_lim != 0) {
1336 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1337 err_code |= ERR_ALERT;
1338 goto out;
1339 }
1340 if (*(args[1]) == 0) {
1341 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345 global.ssl_lim = atol(args[1]);
1346 }
William Lallemandd85f9172012-11-09 17:05:39 +01001347 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001348 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1349 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001350 if (*(args[1]) == 0) {
1351 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 global.comp_rate_lim = atoi(args[1]) * 1024;
1356 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001357 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001358 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1359 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001360 if (global.maxpipes != 0) {
1361 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001362 err_code |= ERR_ALERT;
1363 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001364 }
1365 if (*(args[1]) == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001369 }
1370 global.maxpipes = atol(args[1]);
1371 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001372 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001373 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1374 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
William Lallemande3a7d992012-11-20 11:25:20 +01001380 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001381 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001382 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001383 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1384 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001385 if (*(args[1]) == 0) {
1386 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
1389 }
1390 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001391 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001392 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
1395 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001396 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001399 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 if (global.rlimit_nofile != 0) {
1402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001403 err_code |= ERR_ALERT;
1404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
1406 if (*(args[1]) == 0) {
1407 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001408 err_code |= ERR_ALERT | ERR_FATAL;
1409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 }
1411 global.rlimit_nofile = atol(args[1]);
1412 }
1413 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001414 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 if (global.chroot != NULL) {
1417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001418 err_code |= ERR_ALERT;
1419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 }
1421 if (*(args[1]) == 0) {
1422 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001423 err_code |= ERR_ALERT | ERR_FATAL;
1424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 }
1426 global.chroot = strdup(args[1]);
1427 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001428 else if (!strcmp(args[0], "description")) {
1429 int i, len=0;
1430 char *d;
1431
1432 if (!*args[1]) {
1433 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1434 file, linenum, args[0]);
1435 err_code |= ERR_ALERT | ERR_FATAL;
1436 goto out;
1437 }
1438
Willy Tarreau348acfe2014-04-14 15:00:39 +02001439 for (i = 1; *args[i]; i++)
1440 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001441
1442 if (global.desc)
1443 free(global.desc);
1444
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001445 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001446
Willy Tarreau348acfe2014-04-14 15:00:39 +02001447 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1448 for (i = 2; *args[i]; i++)
1449 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001450 }
1451 else if (!strcmp(args[0], "node")) {
1452 int i;
1453 char c;
1454
William Lallemand1a748ae2015-05-19 16:37:23 +02001455 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1456 goto out;
1457
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001458 for (i=0; args[1][i]; i++) {
1459 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001460 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1461 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001462 break;
1463 }
1464
1465 if (!i || args[1][i]) {
1466 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1467 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1468 file, linenum, args[0]);
1469 err_code |= ERR_ALERT | ERR_FATAL;
1470 goto out;
1471 }
1472
1473 if (global.node)
1474 free(global.node);
1475
1476 global.node = strdup(args[1]);
1477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001479 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 if (global.pidfile != NULL) {
1482 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001483 err_code |= ERR_ALERT;
1484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 }
1486 if (*(args[1]) == 0) {
1487 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001488 err_code |= ERR_ALERT | ERR_FATAL;
1489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 }
1491 global.pidfile = strdup(args[1]);
1492 }
Emeric Bruned760922010-10-22 17:59:25 +02001493 else if (!strcmp(args[0], "unix-bind")) {
1494 int cur_arg = 1;
1495 while (*(args[cur_arg])) {
1496 if (!strcmp(args[cur_arg], "prefix")) {
1497 if (global.unix_bind.prefix != NULL) {
1498 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1499 err_code |= ERR_ALERT;
1500 cur_arg += 2;
1501 continue;
1502 }
1503
1504 if (*(args[cur_arg+1]) == 0) {
1505 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1510 cur_arg += 2;
1511 continue;
1512 }
1513
1514 if (!strcmp(args[cur_arg], "mode")) {
1515
1516 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1517 cur_arg += 2;
1518 continue;
1519 }
1520
1521 if (!strcmp(args[cur_arg], "uid")) {
1522
1523 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1524 cur_arg += 2;
1525 continue;
1526 }
1527
1528 if (!strcmp(args[cur_arg], "gid")) {
1529
1530 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1531 cur_arg += 2;
1532 continue;
1533 }
1534
1535 if (!strcmp(args[cur_arg], "user")) {
1536 struct passwd *user;
1537
1538 user = getpwnam(args[cur_arg + 1]);
1539 if (!user) {
1540 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1541 file, linenum, args[0], args[cur_arg + 1 ]);
1542 err_code |= ERR_ALERT | ERR_FATAL;
1543 goto out;
1544 }
1545
1546 global.unix_bind.ux.uid = user->pw_uid;
1547 cur_arg += 2;
1548 continue;
1549 }
1550
1551 if (!strcmp(args[cur_arg], "group")) {
1552 struct group *group;
1553
1554 group = getgrnam(args[cur_arg + 1]);
1555 if (!group) {
1556 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1557 file, linenum, args[0], args[cur_arg + 1 ]);
1558 err_code |= ERR_ALERT | ERR_FATAL;
1559 goto out;
1560 }
1561
1562 global.unix_bind.ux.gid = group->gr_gid;
1563 cur_arg += 2;
1564 continue;
1565 }
1566
Willy Tarreaub48f9582011-09-05 01:17:06 +02001567 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001568 file, linenum, args[0]);
1569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
1571 }
1572 }
William Lallemand0f99e342011-10-12 17:50:54 +02001573 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1574 /* delete previous herited or defined syslog servers */
1575 struct logsrv *back;
1576 struct logsrv *tmp;
1577
1578 if (*(args[1]) != 0) {
1579 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
1583
1584 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1585 LIST_DEL(&tmp->list);
1586 free(tmp);
1587 }
1588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001590 struct sockaddr_storage *sk;
1591 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001592 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001593 int arg = 0;
1594 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001595
William Lallemand1a748ae2015-05-19 16:37:23 +02001596 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1597 goto out;
1598
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 if (*(args[1]) == 0 || *(args[2]) == 0) {
1600 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001601 err_code |= ERR_ALERT | ERR_FATAL;
1602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 }
William Lallemand0f99e342011-10-12 17:50:54 +02001604
Vincent Bernat02779b62016-04-03 13:48:43 +02001605 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001606
Willy Tarreau18324f52014-06-27 18:10:07 +02001607 /* just after the address, a length may be specified */
1608 if (strcmp(args[arg+2], "len") == 0) {
1609 len = atoi(args[arg+3]);
1610 if (len < 80 || len > 65535) {
1611 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1612 file, linenum, args[arg+3]);
1613 err_code |= ERR_ALERT | ERR_FATAL;
1614 goto out;
1615 }
1616 logsrv->maxlen = len;
1617
1618 /* skip these two args */
1619 arg += 2;
1620 }
1621 else
1622 logsrv->maxlen = MAX_SYSLOG_LEN;
1623
1624 if (logsrv->maxlen > global.max_syslog_len) {
1625 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001626 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1627 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1628 logline = my_realloc2(logline, global.max_syslog_len + 1);
1629 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001630 }
1631
Dragan Dosen1322d092015-09-22 16:05:32 +02001632 /* after the length, a format may be specified */
1633 if (strcmp(args[arg+2], "format") == 0) {
1634 logsrv->format = get_log_format(args[arg+3]);
1635 if (logsrv->format < 0) {
1636 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1637 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001638 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001639 goto out;
1640 }
1641
1642 /* skip these two args */
1643 arg += 2;
1644 }
1645
David Carlier97880bb2016-04-08 10:35:26 +01001646 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1647 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001648 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001649 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001650
Willy Tarreau18324f52014-06-27 18:10:07 +02001651 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001652 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001653 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001655 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 }
1657
William Lallemand0f99e342011-10-12 17:50:54 +02001658 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001659 if (*(args[arg+3])) {
1660 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001661 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001662 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001664 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
1666 }
1667
William Lallemand0f99e342011-10-12 17:50:54 +02001668 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001669 if (*(args[arg+4])) {
1670 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001671 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001672 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001674 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001675 }
1676 }
1677
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001678 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001679 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001680 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001681 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001682 free(logsrv);
1683 goto out;
1684 }
1685 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001686
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001687 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001688 if (port1 != port2) {
1689 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1690 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001691 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001692 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001693 goto out;
1694 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001695
William Lallemand0f99e342011-10-12 17:50:54 +02001696 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001697 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001698 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
William Lallemand0f99e342011-10-12 17:50:54 +02001701 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001702 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001703 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1704 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001705
1706 if (global.log_send_hostname != NULL) {
1707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1708 err_code |= ERR_ALERT;
1709 goto out;
1710 }
1711
1712 if (*(args[1]))
1713 name = args[1];
1714 else
1715 name = hostname;
1716
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001717 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001718 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001719 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001720 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1721 if (global.server_state_base != NULL) {
1722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1723 err_code |= ERR_ALERT;
1724 goto out;
1725 }
1726
1727 if (!*(args[1])) {
1728 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1729 err_code |= ERR_FATAL;
1730 goto out;
1731 }
1732
1733 global.server_state_base = strdup(args[1]);
1734 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001735 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1736 if (global.server_state_file != NULL) {
1737 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1738 err_code |= ERR_ALERT;
1739 goto out;
1740 }
1741
1742 if (!*(args[1])) {
1743 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1744 err_code |= ERR_FATAL;
1745 goto out;
1746 }
1747
1748 global.server_state_file = strdup(args[1]);
1749 }
Kevinm48936af2010-12-22 16:08:21 +00001750 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001751 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1752 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001753 if (*(args[1]) == 0) {
1754 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001758 chunk_destroy(&global.log_tag);
1759 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001760 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001761 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1763 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001764 if (global.spread_checks != 0) {
1765 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001766 err_code |= ERR_ALERT;
1767 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001768 }
1769 if (*(args[1]) == 0) {
1770 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001773 }
1774 global.spread_checks = atol(args[1]);
1775 if (global.spread_checks < 0 || global.spread_checks > 50) {
1776 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001777 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001780 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1781 const char *err;
1782 unsigned int val;
1783
William Lallemand1a748ae2015-05-19 16:37:23 +02001784 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1785 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001786 if (*(args[1]) == 0) {
1787 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791
1792 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1793 if (err) {
1794 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1795 err_code |= ERR_ALERT | ERR_FATAL;
1796 }
1797 global.max_spread_checks = val;
1798 if (global.max_spread_checks < 0) {
1799 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 }
1802 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001803 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1804#ifdef USE_CPU_AFFINITY
1805 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001806 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001807 unsigned long cpus = 0;
1808
1809 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001810 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001811 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001812 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001813 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001814 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001815 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001816 proc = atol(args[1]);
1817 if (proc >= 1 && proc <= LONGBITS)
1818 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001819 }
1820
1821 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001822 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",
1823 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 cur_arg = 2;
1829 while (*args[cur_arg]) {
1830 unsigned int low, high;
1831
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001832 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001833 char *dash = strchr(args[cur_arg], '-');
1834
1835 low = high = str2uic(args[cur_arg]);
1836 if (dash)
1837 high = str2uic(dash + 1);
1838
1839 if (high < low) {
1840 unsigned int swap = low;
1841 low = high;
1842 high = swap;
1843 }
1844
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001845 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001846 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001847 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
1851
1852 while (low <= high)
1853 cpus |= 1UL << low++;
1854 }
1855 else {
1856 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1857 file, linenum, args[0], args[cur_arg]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 cur_arg++;
1862 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001863 for (i = 0; i < LONGBITS; i++)
1864 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001865 global.cpu_map[i] = cpus;
1866#else
1867 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870#endif
1871 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001872 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1873 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1874 goto out;
1875
1876 if (*(args[2]) == 0) {
1877 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
1880 }
1881
1882 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1883 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1884 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
1887 }
1888 }
1889 else if (!strcmp(args[0], "unsetenv")) {
1890 int arg;
1891
1892 if (*(args[1]) == 0) {
1893 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
1896 }
1897
1898 for (arg = 1; *args[arg]; arg++) {
1899 if (unsetenv(args[arg]) != 0) {
1900 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
1903 }
1904 }
1905 }
1906 else if (!strcmp(args[0], "resetenv")) {
1907 extern char **environ;
1908 char **env = environ;
1909
1910 /* args contain variable names to keep, one per argument */
1911 while (*env) {
1912 int arg;
1913
1914 /* look for current variable in among all those we want to keep */
1915 for (arg = 1; *args[arg]; arg++) {
1916 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1917 (*env)[strlen(args[arg])] == '=')
1918 break;
1919 }
1920
1921 /* delete this variable */
1922 if (!*args[arg]) {
1923 char *delim = strchr(*env, '=');
1924
1925 if (!delim || delim - *env >= trash.size) {
1926 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
1929 }
1930
1931 memcpy(trash.str, *env, delim - *env);
1932 trash.str[delim - *env] = 0;
1933
1934 if (unsetenv(trash.str) != 0) {
1935 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939 }
1940 else
1941 env++;
1942 }
1943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001945 struct cfg_kw_list *kwl;
1946 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001947 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001948
1949 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1950 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1951 if (kwl->kw[index].section != CFG_GLOBAL)
1952 continue;
1953 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001954 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001955 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001956 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001957 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001958 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001959 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001960 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001961 err_code |= ERR_WARN;
1962 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001963 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001964 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001965 }
1966 }
1967 }
1968
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001972
Willy Tarreau058e9072009-07-20 09:30:05 +02001973 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001974 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001975 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976}
1977
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001978void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001980 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 defproxy.mode = PR_MODE_TCP;
1982 defproxy.state = PR_STNEW;
1983 defproxy.maxconn = cfg_maxpconn;
1984 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001985 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001986 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001987
Simon Horman66183002013-02-23 10:16:43 +09001988 defproxy.defsrv.check.inter = DEF_CHKINTR;
1989 defproxy.defsrv.check.fastinter = 0;
1990 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001991 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1992 defproxy.defsrv.agent.fastinter = 0;
1993 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001994 defproxy.defsrv.check.rise = DEF_RISETIME;
1995 defproxy.defsrv.check.fall = DEF_FALLTIME;
1996 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1997 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001998 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001999 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002000 defproxy.defsrv.maxqueue = 0;
2001 defproxy.defsrv.minconn = 0;
2002 defproxy.defsrv.maxconn = 0;
2003 defproxy.defsrv.slowstart = 0;
2004 defproxy.defsrv.onerror = DEF_HANA_ONERR;
2005 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
2006 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09002007
2008 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002009 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010}
2011
Willy Tarreauade5ec42010-01-28 19:33:49 +01002012
Willy Tarreau63af98d2014-05-18 08:11:41 +02002013/* This function createss a new req* or rsp* rule to the proxy. It compiles the
2014 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
2015 * ERR_FATAL in case of error.
2016 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01002017static int create_cond_regex_rule(const char *file, int line,
2018 struct proxy *px, int dir, int action, int flags,
2019 const char *cmd, const char *reg, const char *repl,
2020 const char **cond_start)
2021{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002022 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002023 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002024 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002025 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002026 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002027 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002028 int cs;
2029 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002030
2031 if (px == &defproxy) {
2032 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002033 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002034 goto err;
2035 }
2036
2037 if (*reg == 0) {
2038 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002039 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002040 goto err;
2041 }
2042
2043 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002044 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002045
Willy Tarreau5321c422010-01-28 20:35:13 +01002046 if (cond_start &&
2047 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002048 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2049 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2050 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002051 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002052 goto err;
2053 }
2054 }
2055 else if (cond_start && **cond_start) {
2056 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2057 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002058 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002059 goto err;
2060 }
2061
Willy Tarreau63af98d2014-05-18 08:11:41 +02002062 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002063 (dir == SMP_OPT_DIR_REQ) ?
2064 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2065 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2066 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002067
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002068 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002069 if (!preg) {
2070 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002071 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002072 goto err;
2073 }
2074
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002075 cs = !(flags & REG_ICASE);
2076 cap = !(flags & REG_NOSUB);
2077 error = NULL;
2078 if (!regex_comp(reg, preg, cs, cap, &error)) {
2079 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2080 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002081 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002082 goto err;
2083 }
2084
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002085 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002086 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002087 if (repl && err) {
2088 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2089 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002090 ret_code |= ERR_ALERT | ERR_FATAL;
2091 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002092 }
2093
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002094 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002095 ret_code |= ERR_WARN;
2096
2097 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002098
Willy Tarreau63af98d2014-05-18 08:11:41 +02002099 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002100 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002101 err:
2102 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002103 free(errmsg);
2104 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002105}
2106
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107/*
William Lallemand51097192015-04-14 16:35:22 +02002108 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002109 * Returns the error code, 0 if OK, or any combination of :
2110 * - ERR_ABORT: must abort ASAP
2111 * - ERR_FATAL: we can continue parsing but not start the service
2112 * - ERR_WARN: a warning has been emitted
2113 * - ERR_ALERT: an alert has been emitted
2114 * Only the two first ones can stop processing, the two others are just
2115 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002117int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2118{
2119 static struct peers *curpeers = NULL;
2120 struct peer *newpeer = NULL;
2121 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002122 struct bind_conf *bind_conf;
2123 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002124 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002125 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002126
2127 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002128 if (!*args[1]) {
2129 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002130 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002131 goto out;
2132 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002133
William Lallemand6e62fb62015-04-28 16:55:23 +02002134 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2135 goto out;
2136
Emeric Brun32da3c42010-09-23 18:39:19 +02002137 err = invalid_char(args[1]);
2138 if (err) {
2139 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2140 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002141 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002142 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002143 }
2144
2145 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2146 /*
2147 * If there are two proxies with the same name only following
2148 * combinations are allowed:
2149 */
2150 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002151 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 +02002152 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002153 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002154 }
2155 }
2156
Vincent Bernat02779b62016-04-03 13:48:43 +02002157 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2159 err_code |= ERR_ALERT | ERR_ABORT;
2160 goto out;
2161 }
2162
2163 curpeers->next = peers;
2164 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002165 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002166 curpeers->conf.line = linenum;
2167 curpeers->last_change = now.tv_sec;
2168 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002169 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002170 }
2171 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002172 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002173 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002174 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002175
2176 if (!*args[2]) {
2177 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2178 file, linenum, args[0]);
2179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
2181 }
2182
2183 err = invalid_char(args[1]);
2184 if (err) {
2185 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2186 file, linenum, *err, args[1]);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190
Vincent Bernat02779b62016-04-03 13:48:43 +02002191 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002192 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2193 err_code |= ERR_ALERT | ERR_ABORT;
2194 goto out;
2195 }
2196
2197 /* the peers are linked backwards first */
2198 curpeers->count++;
2199 newpeer->next = curpeers->remote;
2200 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002201 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002202 newpeer->conf.line = linenum;
2203
2204 newpeer->last_change = now.tv_sec;
2205 newpeer->id = strdup(args[1]);
2206
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002207 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002208 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002209 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002212 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002213
2214 proto = protocol_by_family(sk->ss_family);
2215 if (!proto || !proto->connect) {
2216 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2217 file, linenum, args[0], args[1]);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
2220 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002221
2222 if (port1 != port2) {
2223 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2224 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
2227 }
2228
Willy Tarreau2aa38802013-02-20 19:20:59 +01002229 if (!port1) {
2230 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2231 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
2234 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002235
Emeric Brun32da3c42010-09-23 18:39:19 +02002236 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002237 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002238 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002239 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002240
Emeric Brun32da3c42010-09-23 18:39:19 +02002241 if (strcmp(newpeer->id, localpeer) == 0) {
2242 /* Current is local peer, it define a frontend */
2243 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002244 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002245
2246 if (!curpeers->peers_fe) {
2247 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2248 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2249 err_code |= ERR_ALERT | ERR_ABORT;
2250 goto out;
2251 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002252
Willy Tarreau237250c2011-07-29 01:49:03 +02002253 init_new_proxy(curpeers->peers_fe);
2254 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002255 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002256 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2257 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002258 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002259
2260 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2261
Willy Tarreau902636f2013-03-10 19:44:48 +01002262 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2263 if (errmsg && *errmsg) {
2264 indent_msg(&errmsg, 2);
2265 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002266 }
2267 else
2268 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2269 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002270 err_code |= ERR_FATAL;
2271 goto out;
2272 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002273
2274 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002275 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002276 l->maxconn = curpeers->peers_fe->maxconn;
2277 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002278 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002279 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002280 l->analysers |= curpeers->peers_fe->fe_req_ana;
2281 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002282 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2283 global.maxsock += l->maxconn;
2284 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002285 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002286 else {
2287 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2288 file, linenum, args[0], args[1],
2289 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2290 err_code |= ERR_FATAL;
2291 goto out;
2292 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002293 }
2294 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002295 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2296 curpeers->state = PR_STSTOPPED;
2297 }
2298 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2299 curpeers->state = PR_STNEW;
2300 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002301 else if (*args[0] != 0) {
2302 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306
2307out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002308 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002309 return err_code;
2310}
2311
Baptiste Assmann325137d2015-04-13 23:40:55 +02002312/*
2313 * Parse a <resolvers> section.
2314 * Returns the error code, 0 if OK, or any combination of :
2315 * - ERR_ABORT: must abort ASAP
2316 * - ERR_FATAL: we can continue parsing but not start the service
2317 * - ERR_WARN: a warning has been emitted
2318 * - ERR_ALERT: an alert has been emitted
2319 * Only the two first ones can stop processing, the two others are just
2320 * indicators.
2321 */
2322int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2323{
2324 static struct dns_resolvers *curr_resolvers = NULL;
2325 struct dns_nameserver *newnameserver = NULL;
2326 const char *err;
2327 int err_code = 0;
2328 char *errmsg = NULL;
2329
2330 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2331 if (!*args[1]) {
2332 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2333 err_code |= ERR_ALERT | ERR_ABORT;
2334 goto out;
2335 }
2336
2337 err = invalid_char(args[1]);
2338 if (err) {
2339 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2340 file, linenum, *err, args[0], args[1]);
2341 err_code |= ERR_ALERT | ERR_ABORT;
2342 goto out;
2343 }
2344
2345 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2346 /* Error if two resolvers owns the same name */
2347 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2348 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2349 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2350 err_code |= ERR_ALERT | ERR_ABORT;
2351 }
2352 }
2353
Vincent Bernat02779b62016-04-03 13:48:43 +02002354 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2356 err_code |= ERR_ALERT | ERR_ABORT;
2357 goto out;
2358 }
2359
2360 /* default values */
2361 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2362 curr_resolvers->conf.file = strdup(file);
2363 curr_resolvers->conf.line = linenum;
2364 curr_resolvers->id = strdup(args[1]);
2365 curr_resolvers->query_ids = EB_ROOT;
2366 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002367 curr_resolvers->hold.valid = 10000;
2368 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002369 curr_resolvers->resolve_retries = 3;
2370 LIST_INIT(&curr_resolvers->nameserver_list);
2371 LIST_INIT(&curr_resolvers->curr_resolution);
2372 }
2373 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2374 struct sockaddr_storage *sk;
2375 int port1, port2;
2376 struct protocol *proto;
2377
2378 if (!*args[2]) {
2379 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2380 file, linenum, args[0]);
2381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
2383 }
2384
2385 err = invalid_char(args[1]);
2386 if (err) {
2387 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2388 file, linenum, *err, args[1]);
2389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
2391 }
2392
Baptiste Assmanna315c552015-11-02 22:55:49 +01002393 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2394 /* Error if two resolvers owns the same name */
2395 if (strcmp(newnameserver->id, args[1]) == 0) {
2396 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2397 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2398 err_code |= ERR_ALERT | ERR_FATAL;
2399 }
2400 }
2401
Vincent Bernat02779b62016-04-03 13:48:43 +02002402 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002403 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2404 err_code |= ERR_ALERT | ERR_ABORT;
2405 goto out;
2406 }
2407
2408 /* the nameservers are linked backward first */
2409 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2410 curr_resolvers->count_nameservers++;
2411 newnameserver->resolvers = curr_resolvers;
2412 newnameserver->conf.file = strdup(file);
2413 newnameserver->conf.line = linenum;
2414 newnameserver->id = strdup(args[1]);
2415
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002416 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002417 if (!sk) {
2418 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
2421 }
2422
2423 proto = protocol_by_family(sk->ss_family);
2424 if (!proto || !proto->connect) {
2425 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2426 file, linenum, args[0], args[1]);
2427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
2429 }
2430
2431 if (port1 != port2) {
2432 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2433 file, linenum, args[0], args[1], args[2]);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002438 if (!port1 && !port2) {
2439 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2440 file, linenum, args[0], args[1]);
2441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
2443 }
2444
Baptiste Assmann325137d2015-04-13 23:40:55 +02002445 newnameserver->addr = *sk;
2446 }
2447 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2448 const char *res;
2449 unsigned int time;
2450
2451 if (!*args[2]) {
2452 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2453 file, linenum, args[0]);
2454 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
2458 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2459 if (res) {
2460 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2461 file, linenum, *res, args[0]);
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465 if (strcmp(args[1], "valid") == 0)
2466 curr_resolvers->hold.valid = time;
2467 else {
2468 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2469 file, linenum, args[0], args[1]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
2474 }
2475 else if (strcmp(args[0], "resolve_retries") == 0) {
2476 if (!*args[1]) {
2477 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2478 file, linenum, args[0]);
2479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
2481 }
2482 curr_resolvers->resolve_retries = atoi(args[1]);
2483 }
2484 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002485 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002486 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2487 file, linenum, args[0]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002491 else if (strcmp(args[1], "retry") == 0) {
2492 const char *res;
2493 unsigned int timeout_retry;
2494
2495 if (!*args[2]) {
2496 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2497 file, linenum, args[0], args[1]);
2498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
2501 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2502 if (res) {
2503 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2504 file, linenum, *res, args[0], args[1]);
2505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
2508 curr_resolvers->timeout.retry = timeout_retry;
2509 }
2510 else {
2511 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2512 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
2515 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002516 } /* neither "nameserver" nor "resolvers" */
2517 else if (*args[0] != 0) {
2518 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
2521 }
2522
2523 out:
2524 free(errmsg);
2525 return err_code;
2526}
Simon Horman0d16a402015-01-30 11:22:58 +09002527
2528/*
William Lallemand51097192015-04-14 16:35:22 +02002529 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002530 * Returns the error code, 0 if OK, or any combination of :
2531 * - ERR_ABORT: must abort ASAP
2532 * - ERR_FATAL: we can continue parsing but not start the service
2533 * - ERR_WARN: a warning has been emitted
2534 * - ERR_ALERT: an alert has been emitted
2535 * Only the two first ones can stop processing, the two others are just
2536 * indicators.
2537 */
2538int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2539{
2540 static struct mailers *curmailers = NULL;
2541 struct mailer *newmailer = NULL;
2542 const char *err;
2543 int err_code = 0;
2544 char *errmsg = NULL;
2545
2546 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2547 if (!*args[1]) {
2548 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2549 err_code |= ERR_ALERT | ERR_ABORT;
2550 goto out;
2551 }
2552
2553 err = invalid_char(args[1]);
2554 if (err) {
2555 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2556 file, linenum, *err, args[0], args[1]);
2557 err_code |= ERR_ALERT | ERR_ABORT;
2558 goto out;
2559 }
2560
2561 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2562 /*
2563 * If there are two proxies with the same name only following
2564 * combinations are allowed:
2565 */
2566 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002567 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 +09002568 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002570 }
2571 }
2572
Vincent Bernat02779b62016-04-03 13:48:43 +02002573 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2575 err_code |= ERR_ALERT | ERR_ABORT;
2576 goto out;
2577 }
2578
2579 curmailers->next = mailers;
2580 mailers = curmailers;
2581 curmailers->conf.file = strdup(file);
2582 curmailers->conf.line = linenum;
2583 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002584 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2585 * But need enough time so that timeouts don't occur
2586 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002587 }
2588 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2589 struct sockaddr_storage *sk;
2590 int port1, port2;
2591 struct protocol *proto;
2592
2593 if (!*args[2]) {
2594 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2595 file, linenum, args[0]);
2596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
2598 }
2599
2600 err = invalid_char(args[1]);
2601 if (err) {
2602 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2603 file, linenum, *err, args[1]);
2604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
2606 }
2607
Vincent Bernat02779b62016-04-03 13:48:43 +02002608 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002609 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2610 err_code |= ERR_ALERT | ERR_ABORT;
2611 goto out;
2612 }
2613
2614 /* the mailers are linked backwards first */
2615 curmailers->count++;
2616 newmailer->next = curmailers->mailer_list;
2617 curmailers->mailer_list = newmailer;
2618 newmailer->mailers = curmailers;
2619 newmailer->conf.file = strdup(file);
2620 newmailer->conf.line = linenum;
2621
2622 newmailer->id = strdup(args[1]);
2623
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002624 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002625 if (!sk) {
2626 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630
2631 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002632 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2633 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002634 file, linenum, args[0], args[1]);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637 }
2638
2639 if (port1 != port2) {
2640 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2641 file, linenum, args[0], args[1], args[2]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
2646 if (!port1) {
2647 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2648 file, linenum, args[0], args[1], args[2]);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651 }
2652
2653 newmailer->addr = *sk;
2654 newmailer->proto = proto;
2655 newmailer->xprt = &raw_sock;
2656 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002657 }
2658 else if (strcmp(args[0], "timeout") == 0) {
2659 if (!*args[1]) {
2660 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2661 file, linenum, args[0]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665 else if (strcmp(args[1], "mail") == 0) {
2666 const char *res;
2667 unsigned int timeout_mail;
2668 if (!*args[2]) {
2669 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2670 file, linenum, args[0], args[1]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2675 if (res) {
2676 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2677 file, linenum, *res, args[0]);
2678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
2680 }
2681 if (timeout_mail <= 0) {
2682 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686 curmailers->timeout.mail = timeout_mail;
2687 } else {
2688 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2689 file, linenum, args[0], args[1]);
2690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
2692 }
2693 }
Simon Horman0d16a402015-01-30 11:22:58 +09002694 else if (*args[0] != 0) {
2695 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699
2700out:
2701 free(errmsg);
2702 return err_code;
2703}
2704
Simon Horman9dc49962015-01-30 11:22:59 +09002705static void free_email_alert(struct proxy *p)
2706{
2707 free(p->email_alert.mailers.name);
2708 p->email_alert.mailers.name = NULL;
2709 free(p->email_alert.from);
2710 p->email_alert.from = NULL;
2711 free(p->email_alert.to);
2712 p->email_alert.to = NULL;
2713 free(p->email_alert.myhostname);
2714 p->email_alert.myhostname = NULL;
2715}
2716
Willy Tarreau3842f002009-06-14 11:39:52 +02002717int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718{
2719 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002720 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002721 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002722 int rc;
2723 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002724 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002725 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002726 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002727 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002728 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729
Willy Tarreau977b8e42006-12-29 14:19:17 +01002730 if (!strcmp(args[0], "listen"))
2731 rc = PR_CAP_LISTEN;
2732 else if (!strcmp(args[0], "frontend"))
2733 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002734 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002735 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002736 else
2737 rc = PR_CAP_NONE;
2738
2739 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 if (!*args[1]) {
2741 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002742 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_ABORT;
2745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002747
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002748 err = invalid_char(args[1]);
2749 if (err) {
2750 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2751 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002752 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002753 }
2754
Willy Tarreau8f50b682015-05-26 11:45:02 +02002755 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2756 if (curproxy) {
2757 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2758 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2759 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002760 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002761 }
2762
Vincent Bernat02779b62016-04-03 13:48:43 +02002763 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002765 err_code |= ERR_ALERT | ERR_ABORT;
2766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002768
Willy Tarreau97cb7802010-01-03 20:23:58 +01002769 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 curproxy->next = proxy;
2771 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002772 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2773 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002774 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002776 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002777 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778
William Lallemand6e62fb62015-04-28 16:55:23 +02002779 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2780 if (curproxy->cap & PR_CAP_FE)
2781 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
2784
2785 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002786 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002787 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002788
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002791 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002792 curproxy->no_options = defproxy.no_options;
2793 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002794 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002795 curproxy->except_net = defproxy.except_net;
2796 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002797 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002798 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002800 if (defproxy.fwdfor_hdr_len) {
2801 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2802 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2803 }
2804
Willy Tarreaub86db342009-11-30 11:50:16 +01002805 if (defproxy.orgto_hdr_len) {
2806 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2807 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2808 }
2809
Mark Lamourinec2247f02012-01-04 13:02:01 -05002810 if (defproxy.server_id_hdr_len) {
2811 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2812 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2813 }
2814
Willy Tarreau977b8e42006-12-29 14:19:17 +01002815 if (curproxy->cap & PR_CAP_FE) {
2816 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002817 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002818 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002819
2820 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002821 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2822 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002823
2824 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826
Willy Tarreau977b8e42006-12-29 14:19:17 +01002827 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002828 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002829 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002830 curproxy->fullconn = defproxy.fullconn;
2831 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002832 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002833 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002835 if (defproxy.check_req) {
2836 curproxy->check_req = calloc(1, defproxy.check_len);
2837 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2838 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002839 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002841 if (defproxy.expect_str) {
2842 curproxy->expect_str = strdup(defproxy.expect_str);
2843 if (defproxy.expect_regex) {
2844 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002845 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2846 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002847 }
2848 }
2849
Willy Tarreau67402132012-05-31 20:40:20 +02002850 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 if (defproxy.cookie_name)
2852 curproxy->cookie_name = strdup(defproxy.cookie_name);
2853 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002854 if (defproxy.cookie_domain)
2855 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002856
Willy Tarreau31936852010-10-06 16:59:56 +02002857 if (defproxy.cookie_maxidle)
2858 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2859
2860 if (defproxy.cookie_maxlife)
2861 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2862
Emeric Brun647caf12009-06-30 17:57:00 +02002863 if (defproxy.rdp_cookie_name)
2864 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2865 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2866
Willy Tarreau01732802007-11-01 22:48:15 +01002867 if (defproxy.url_param_name)
2868 curproxy->url_param_name = strdup(defproxy.url_param_name);
2869 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002870
Benoitaffb4812009-03-25 13:02:10 +01002871 if (defproxy.hh_name)
2872 curproxy->hh_name = strdup(defproxy.hh_name);
2873 curproxy->hh_len = defproxy.hh_len;
2874 curproxy->hh_match_domain = defproxy.hh_match_domain;
2875
Willy Tarreauef9a3602012-12-08 22:29:20 +01002876 if (defproxy.conn_src.iface_name)
2877 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2878 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002879 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002880#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002881 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002882#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002883 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002886 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887 if (defproxy.capture_name)
2888 curproxy->capture_name = strdup(defproxy.capture_name);
2889 curproxy->capture_namelen = defproxy.capture_namelen;
2890 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892
Willy Tarreau977b8e42006-12-29 14:19:17 +01002893 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002894 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002895 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002896 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002897 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002898 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899 curproxy->mon_net = defproxy.mon_net;
2900 curproxy->mon_mask = defproxy.mon_mask;
2901 if (defproxy.monitor_uri)
2902 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2903 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002904 if (defproxy.defbe.name)
2905 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002906
2907 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002908 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2909 if (curproxy->conf.logformat_string &&
2910 curproxy->conf.logformat_string != default_http_log_format &&
2911 curproxy->conf.logformat_string != default_tcp_log_format &&
2912 curproxy->conf.logformat_string != clf_http_log_format)
2913 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2914
2915 if (defproxy.conf.lfs_file) {
2916 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2917 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2918 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002919
2920 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2921 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2922 if (curproxy->conf.logformat_sd_string &&
2923 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2924 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2925
2926 if (defproxy.conf.lfsd_file) {
2927 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2928 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2929 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002930 }
2931
2932 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002933 curproxy->timeout.connect = defproxy.timeout.connect;
2934 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002935 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002936 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002937 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002938 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002939 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002940 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002941 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002942 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002943 }
2944
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002946 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002947
2948 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002949 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002950 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002951 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002952 LIST_INIT(&node->list);
2953 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2954 }
2955
Willy Tarreau62a61232013-04-12 18:13:46 +02002956 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2957 if (curproxy->conf.uniqueid_format_string)
2958 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2959
Dragan Dosen43885c72015-10-01 13:18:13 +02002960 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002961
Willy Tarreau62a61232013-04-12 18:13:46 +02002962 if (defproxy.conf.uif_file) {
2963 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2964 curproxy->conf.uif_line = defproxy.conf.uif_line;
2965 }
William Lallemanda73203e2012-03-12 12:48:57 +01002966
2967 /* copy default header unique id */
2968 if (defproxy.header_unique_id)
2969 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2970
William Lallemand82fe75c2012-10-23 10:25:10 +02002971 /* default compression options */
2972 if (defproxy.comp != NULL) {
2973 curproxy->comp = calloc(1, sizeof(struct comp));
2974 curproxy->comp->algos = defproxy.comp->algos;
2975 curproxy->comp->types = defproxy.comp->types;
2976 }
2977
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002979 curproxy->conf.used_listener_id = EB_ROOT;
2980 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002981
Simon Horman98637e52014-06-20 12:30:16 +09002982 if (defproxy.check_path)
2983 curproxy->check_path = strdup(defproxy.check_path);
2984 if (defproxy.check_command)
2985 curproxy->check_command = strdup(defproxy.check_command);
2986
Simon Horman9dc49962015-01-30 11:22:59 +09002987 if (defproxy.email_alert.mailers.name)
2988 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2989 if (defproxy.email_alert.from)
2990 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2991 if (defproxy.email_alert.to)
2992 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2993 if (defproxy.email_alert.myhostname)
2994 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002995 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002996 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002997
Willy Tarreau93893792009-07-23 13:19:11 +02002998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 }
3000 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
3001 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003002 /* FIXME-20070101: we should do this too at the end of the
3003 * config parsing to free all default values.
3004 */
William Lallemand6e62fb62015-04-28 16:55:23 +02003005 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
3006 err_code |= ERR_ABORT;
3007 goto out;
3008 }
3009
Willy Tarreaua534fea2008-08-03 12:19:50 +02003010 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003011 free(defproxy.check_command);
3012 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003013 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003014 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003015 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003016 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003017 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003018 free(defproxy.capture_name);
3019 free(defproxy.monitor_uri);
3020 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003021 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003022 free(defproxy.fwdfor_hdr_name);
3023 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003024 free(defproxy.orgto_hdr_name);
3025 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003026 free(defproxy.server_id_hdr_name);
3027 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003028 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003029 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003030 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003031 free(defproxy.expect_regex);
3032 defproxy.expect_regex = NULL;
3033 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003034
Willy Tarreau62a61232013-04-12 18:13:46 +02003035 if (defproxy.conf.logformat_string != default_http_log_format &&
3036 defproxy.conf.logformat_string != default_tcp_log_format &&
3037 defproxy.conf.logformat_string != clf_http_log_format)
3038 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003039
Willy Tarreau62a61232013-04-12 18:13:46 +02003040 free(defproxy.conf.uniqueid_format_string);
3041 free(defproxy.conf.lfs_file);
3042 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003043 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003044 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003045
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003046 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3047 free(defproxy.conf.logformat_sd_string);
3048 free(defproxy.conf.lfsd_file);
3049
Willy Tarreaua534fea2008-08-03 12:19:50 +02003050 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003051 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003052
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 /* we cannot free uri_auth because it might already be used */
3054 init_default_instance();
3055 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003056 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3057 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003058 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 }
3061 else if (curproxy == NULL) {
3062 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003066
3067 /* update the current file and line being parsed */
3068 curproxy->conf.args.file = curproxy->conf.file;
3069 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003070
3071 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003072 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3073 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3074 if (err_code & ERR_FATAL)
3075 goto out;
3076 }
3077 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003078 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003079 int cur_arg;
3080
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 if (curproxy == &defproxy) {
3082 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003086 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088
Willy Tarreau24709282013-03-10 21:32:12 +01003089 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003090 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003095
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003096 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003097
3098 /* use default settings for unix sockets */
3099 bind_conf->ux.uid = global.unix_bind.ux.uid;
3100 bind_conf->ux.gid = global.unix_bind.ux.gid;
3101 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003102
3103 /* NOTE: the following line might create several listeners if there
3104 * are comma-separated IPs or port ranges. So all further processing
3105 * will have to be applied to all listeners created after last_listen.
3106 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003107 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3108 if (errmsg && *errmsg) {
3109 indent_msg(&errmsg, 2);
3110 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003111 }
3112 else
3113 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3114 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
3117 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003118
Willy Tarreau4348fad2012-09-20 16:48:07 +02003119 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3120 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003121 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003122 }
3123
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003124 cur_arg = 2;
3125 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003126 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003127 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003128 char *err;
3129
Willy Tarreau26982662012-09-12 23:17:10 +02003130 kw = bind_find_kw(args[cur_arg]);
3131 if (kw) {
3132 char *err = NULL;
3133 int code;
3134
3135 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003136 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3137 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003138 cur_arg += 1 + kw->skip ;
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
3141 }
3142
Willy Tarreau4348fad2012-09-20 16:48:07 +02003143 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003144 err_code |= code;
3145
3146 if (code) {
3147 if (err && *err) {
3148 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003149 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003150 }
3151 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003152 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3153 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003154 if (code & ERR_FATAL) {
3155 free(err);
3156 cur_arg += 1 + kw->skip;
3157 goto out;
3158 }
3159 }
3160 free(err);
3161 cur_arg += 1 + kw->skip;
3162 continue;
3163 }
3164
Willy Tarreau8638f482012-09-18 18:01:17 +02003165 err = NULL;
3166 if (!bind_dumped) {
3167 bind_dump_kws(&err);
3168 indent_msg(&err, 4);
3169 bind_dumped = 1;
3170 }
3171
3172 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3173 file, linenum, args[0], args[1], args[cur_arg],
3174 err ? " Registered keywords :" : "", err ? err : "");
3175 free(err);
3176
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003179 }
Willy Tarreau93893792009-07-23 13:19:11 +02003180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 }
3182 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003183 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3185 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003189 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003191
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 /* flush useless bits */
3193 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003196 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003197 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003199
William Lallemanddf1425a2015-04-28 20:17:49 +02003200 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3201 goto out;
3202
Willy Tarreau1c47f852006-07-09 08:22:27 +02003203 if (!*args[1]) {
3204 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003208 }
3209
Willy Tarreaua534fea2008-08-03 12:19:50 +02003210 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003211 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003212 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003213 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003214 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3215
Willy Tarreau93893792009-07-23 13:19:11 +02003216 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003219 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3220 goto out;
3221
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3223 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3224 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3225 else {
3226 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
3230 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003231 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003232 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003233
3234 if (curproxy == &defproxy) {
3235 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3236 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003239 }
3240
William Lallemanddf1425a2015-04-28 20:17:49 +02003241 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3242 goto out;
3243
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003244 if (!*args[1]) {
3245 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003249 }
3250
3251 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003252 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003253 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003254
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003255 if (curproxy->uuid <= 0) {
3256 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003257 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003260 }
3261
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003262 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3263 if (node) {
3264 struct proxy *target = container_of(node, struct proxy, conf.id);
3265 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3266 file, linenum, proxy_type_str(curproxy), curproxy->id,
3267 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003272 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003273 else if (!strcmp(args[0], "description")) {
3274 int i, len=0;
3275 char *d;
3276
Cyril Bonté99ed3272010-01-24 23:29:44 +01003277 if (curproxy == &defproxy) {
3278 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3279 file, linenum, args[0]);
3280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
3282 }
3283
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003284 if (!*args[1]) {
3285 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3286 file, linenum, args[0]);
3287 return -1;
3288 }
3289
Willy Tarreau348acfe2014-04-14 15:00:39 +02003290 for (i = 1; *args[i]; i++)
3291 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003292
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003293 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003294 curproxy->desc = d;
3295
Willy Tarreau348acfe2014-04-14 15:00:39 +02003296 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3297 for (i = 2; *args[i]; i++)
3298 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003299
3300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003302 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 curproxy->state = PR_STSTOPPED;
3305 }
3306 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003307 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 curproxy->state = PR_STNEW;
3310 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003311 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3312 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003313 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003314
3315 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003316 unsigned int low, high;
3317
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003318 if (strcmp(args[cur_arg], "all") == 0) {
3319 set = 0;
3320 break;
3321 }
3322 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003323 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003324 }
3325 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003326 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003327 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003328 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003329 char *dash = strchr(args[cur_arg], '-');
3330
3331 low = high = str2uic(args[cur_arg]);
3332 if (dash)
3333 high = str2uic(dash + 1);
3334
3335 if (high < low) {
3336 unsigned int swap = low;
3337 low = high;
3338 high = swap;
3339 }
3340
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003341 if (low < 1 || high > LONGBITS) {
3342 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3343 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003346 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003347 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003348 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003349 }
3350 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003351 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3352 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003355 }
3356 cur_arg++;
3357 }
3358 curproxy->bind_proc = set;
3359 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003360 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003361 if (curproxy == &defproxy) {
3362 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003365 }
3366
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003367 err = invalid_char(args[1]);
3368 if (err) {
3369 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3370 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003372 }
3373
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003374 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003375 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3376 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003379 }
3380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3382 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383
Willy Tarreau977b8e42006-12-29 14:19:17 +01003384 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003386
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 if (*(args[1]) == 0) {
3388 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3389 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003393
Willy Tarreau67402132012-05-31 20:40:20 +02003394 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003395 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003396 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003397 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 curproxy->cookie_name = strdup(args[1]);
3399 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003400
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 cur_arg = 2;
3402 while (*(args[cur_arg])) {
3403 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003404 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003407 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 }
3409 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003410 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
3412 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003413 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 }
3415 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003416 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003418 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003419 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003422 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003424 else if (!strcmp(args[cur_arg], "httponly")) {
3425 curproxy->ck_opts |= PR_CK_HTTPONLY;
3426 }
3427 else if (!strcmp(args[cur_arg], "secure")) {
3428 curproxy->ck_opts |= PR_CK_SECURE;
3429 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003430 else if (!strcmp(args[cur_arg], "domain")) {
3431 if (!*args[cur_arg + 1]) {
3432 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3433 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003436 }
3437
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003438 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003439 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003440 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3441 " dots nor does not start with a dot."
3442 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003443 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003444 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003445 }
3446
3447 err = invalid_domainchar(args[cur_arg + 1]);
3448 if (err) {
3449 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3450 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003453 }
3454
Willy Tarreau68a897b2009-12-03 23:28:34 +01003455 if (!curproxy->cookie_domain) {
3456 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3457 } else {
3458 /* one domain was already specified, add another one by
3459 * building the string which will be returned along with
3460 * the cookie.
3461 */
3462 char *new_ptr;
3463 int new_len = strlen(curproxy->cookie_domain) +
3464 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3465 new_ptr = malloc(new_len);
3466 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3467 free(curproxy->cookie_domain);
3468 curproxy->cookie_domain = new_ptr;
3469 }
Willy Tarreau31936852010-10-06 16:59:56 +02003470 cur_arg++;
3471 }
3472 else if (!strcmp(args[cur_arg], "maxidle")) {
3473 unsigned int maxidle;
3474 const char *res;
3475
3476 if (!*args[cur_arg + 1]) {
3477 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3478 file, linenum, args[cur_arg]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482
3483 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3484 if (res) {
3485 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3486 file, linenum, *res, args[cur_arg]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
3490 curproxy->cookie_maxidle = maxidle;
3491 cur_arg++;
3492 }
3493 else if (!strcmp(args[cur_arg], "maxlife")) {
3494 unsigned int maxlife;
3495 const char *res;
3496
3497 if (!*args[cur_arg + 1]) {
3498 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3499 file, linenum, args[cur_arg]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
3502 }
3503
3504 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3505 if (res) {
3506 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3507 file, linenum, *res, args[cur_arg]);
3508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
3511 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003512 cur_arg++;
3513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003515 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 +02003516 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 }
3520 cur_arg++;
3521 }
Willy Tarreau67402132012-05-31 20:40:20 +02003522 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3524 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003525 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 }
3527
Willy Tarreau67402132012-05-31 20:40:20 +02003528 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3530 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003533
Willy Tarreau67402132012-05-31 20:40:20 +02003534 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003535 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3536 file, linenum);
3537 err_code |= ERR_ALERT | ERR_FATAL;
3538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003540 else if (!strcmp(args[0], "email-alert")) {
3541 if (*(args[1]) == 0) {
3542 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3543 file, linenum, args[0]);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
3547
3548 if (!strcmp(args[1], "from")) {
3549 if (*(args[1]) == 0) {
3550 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3551 file, linenum, args[1]);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
3554 }
3555 free(curproxy->email_alert.from);
3556 curproxy->email_alert.from = strdup(args[2]);
3557 }
3558 else if (!strcmp(args[1], "mailers")) {
3559 if (*(args[1]) == 0) {
3560 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3561 file, linenum, args[1]);
3562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
3564 }
3565 free(curproxy->email_alert.mailers.name);
3566 curproxy->email_alert.mailers.name = strdup(args[2]);
3567 }
3568 else if (!strcmp(args[1], "myhostname")) {
3569 if (*(args[1]) == 0) {
3570 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3571 file, linenum, args[1]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
3575 free(curproxy->email_alert.myhostname);
3576 curproxy->email_alert.myhostname = strdup(args[2]);
3577 }
Simon Horman64e34162015-02-06 11:11:57 +09003578 else if (!strcmp(args[1], "level")) {
3579 curproxy->email_alert.level = get_log_level(args[2]);
3580 if (curproxy->email_alert.level < 0) {
3581 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3582 file, linenum, args[1], args[2]);
3583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
3585 }
3586 }
Simon Horman9dc49962015-01-30 11:22:59 +09003587 else if (!strcmp(args[1], "to")) {
3588 if (*(args[1]) == 0) {
3589 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3590 file, linenum, args[1]);
3591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
3593 }
3594 free(curproxy->email_alert.to);
3595 curproxy->email_alert.to = strdup(args[2]);
3596 }
3597 else {
3598 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3599 file, linenum, args[1]);
3600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
3602 }
Simon Horman64e34162015-02-06 11:11:57 +09003603 /* Indicate that the email_alert is at least partially configured */
3604 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003605 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003606 else if (!strcmp(args[0], "external-check")) {
3607 if (*(args[1]) == 0) {
3608 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3609 file, linenum, args[0]);
3610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
3612 }
3613
3614 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003615 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003616 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003617 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003618 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3619 file, linenum, args[1]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623 free(curproxy->check_command);
3624 curproxy->check_command = strdup(args[2]);
3625 }
3626 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003627 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003628 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003629 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003630 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3631 file, linenum, args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 free(curproxy->check_path);
3636 curproxy->check_path = strdup(args[2]);
3637 }
3638 else {
3639 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3640 file, linenum, args[1]);
3641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
3643 }
3644 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003645 else if (!strcmp(args[0], "persist")) { /* persist */
3646 if (*(args[1]) == 0) {
3647 Alert("parsing [%s:%d] : missing persist method.\n",
3648 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003651 }
3652
3653 if (!strncmp(args[1], "rdp-cookie", 10)) {
3654 curproxy->options2 |= PR_O2_RDPC_PRST;
3655
Emeric Brunb982a3d2010-01-04 15:45:53 +01003656 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003657 const char *beg, *end;
3658
3659 beg = args[1] + 11;
3660 end = strchr(beg, ')');
3661
William Lallemanddf1425a2015-04-28 20:17:49 +02003662 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3663 goto out;
3664
Emeric Brun647caf12009-06-30 17:57:00 +02003665 if (!end || end == beg) {
3666 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3667 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003670 }
3671
3672 free(curproxy->rdp_cookie_name);
3673 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3674 curproxy->rdp_cookie_len = end-beg;
3675 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003676 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003677 free(curproxy->rdp_cookie_name);
3678 curproxy->rdp_cookie_name = strdup("msts");
3679 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3680 }
3681 else { /* syntax */
3682 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3683 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003686 }
3687 }
3688 else {
3689 Alert("parsing [%s:%d] : unknown persist method.\n",
3690 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003693 }
3694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003696 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003700 else if (!strcmp(args[0], "load-server-state-from-file")) {
3701 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3702 err_code |= ERR_WARN;
3703 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3704 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3705 }
3706 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3707 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3708 }
3709 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3710 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3711 }
3712 else {
3713 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3714 file, linenum, args[0], args[1]);
3715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
3717 }
3718 }
3719 else if (!strcmp(args[0], "server-state-file-name")) {
3720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3721 err_code |= ERR_WARN;
3722 if (*(args[1]) == 0) {
3723 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3724 file, linenum, args[0]);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
3728 else if (!strcmp(args[1], "use-backend-name"))
3729 curproxy->server_state_file_name = strdup(curproxy->id);
3730 else
3731 curproxy->server_state_file_name = strdup(args[1]);
3732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003733 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003734 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003735 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003736
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003738 if (curproxy == &defproxy) {
3739 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743
William Lallemand1a748ae2015-05-19 16:37:23 +02003744 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3745 goto out;
3746
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 if (*(args[4]) == 0) {
3748 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3749 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003753 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 curproxy->capture_name = strdup(args[2]);
3755 curproxy->capture_namelen = strlen(curproxy->capture_name);
3756 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 curproxy->to_log |= LW_COOKIE;
3758 }
3759 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3760 struct cap_hdr *hdr;
3761
3762 if (curproxy == &defproxy) {
3763 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 +02003764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 }
3767
William Lallemand1a748ae2015-05-19 16:37:23 +02003768 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3769 goto out;
3770
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3772 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3773 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
3777
Vincent Bernat02779b62016-04-03 13:48:43 +02003778 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 hdr->next = curproxy->req_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_req_cap++;
3785 curproxy->req_cap = hdr;
3786 curproxy->to_log |= LW_REQHDR;
3787 }
3788 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3789 struct cap_hdr *hdr;
3790
3791 if (curproxy == &defproxy) {
3792 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 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 }
3796
William Lallemand1a748ae2015-05-19 16:37:23 +02003797 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3798 goto out;
3799
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3801 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3802 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003806 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 hdr->next = curproxy->rsp_cap;
3808 hdr->name = strdup(args[3]);
3809 hdr->namelen = strlen(args[3]);
3810 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003811 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 hdr->index = curproxy->nb_rsp_cap++;
3813 curproxy->rsp_cap = hdr;
3814 curproxy->to_log |= LW_RSPHDR;
3815 }
3816 else {
3817 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3818 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 }
3822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003826
William Lallemanddf1425a2015-04-28 20:17:49 +02003827 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3828 goto out;
3829
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 if (*(args[1]) == 0) {
3831 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 }
3836 curproxy->conn_retries = atol(args[1]);
3837 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003838 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003839 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003840
3841 if (curproxy == &defproxy) {
3842 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846
Willy Tarreau20b0de52012-12-24 15:45:22 +01003847 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003848 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003849 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3850 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3851 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3852 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003853 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 +01003854 file, linenum, args[0]);
3855 err_code |= ERR_WARN;
3856 }
3857
Willy Tarreauff011f22011-01-06 17:51:27 +01003858 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003859
Willy Tarreauff011f22011-01-06 17:51:27 +01003860 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003861 err_code |= ERR_ALERT | ERR_ABORT;
3862 goto out;
3863 }
3864
Willy Tarreau5002f572014-04-23 01:32:02 +02003865 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003866 err_code |= warnif_cond_conflicts(rule->cond,
3867 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3868 file, linenum);
3869
Willy Tarreauff011f22011-01-06 17:51:27 +01003870 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003871 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003872 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003873 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003874
3875 if (curproxy == &defproxy) {
3876 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
3879 }
3880
3881 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003882 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003883 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3884 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003885 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3886 file, linenum, args[0]);
3887 err_code |= ERR_WARN;
3888 }
3889
3890 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3891
3892 if (!rule) {
3893 err_code |= ERR_ALERT | ERR_ABORT;
3894 goto out;
3895 }
3896
3897 err_code |= warnif_cond_conflicts(rule->cond,
3898 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3899 file, linenum);
3900
3901 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3902 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003903 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3904 /* set the header name and length into the proxy structure */
3905 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3906 err_code |= ERR_WARN;
3907
3908 if (!*args[1]) {
3909 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3910 file, linenum, args[0]);
3911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
3913 }
3914
3915 /* set the desired header name */
3916 free(curproxy->server_id_hdr_name);
3917 curproxy->server_id_hdr_name = strdup(args[1]);
3918 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3919 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003920 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003921 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003922
Willy Tarreaub099aca2008-10-12 17:26:37 +02003923 if (curproxy == &defproxy) {
3924 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003927 }
3928
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003929 /* emulate "block" using "http-request block". Since these rules are supposed to
3930 * be processed before all http-request rules, we put them into their own list
3931 * and will insert them at the end.
3932 */
3933 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3934 if (!rule) {
3935 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003936 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003937 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003938 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3939 err_code |= warnif_cond_conflicts(rule->cond,
3940 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3941 file, linenum);
3942 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003943
3944 if (!already_warned(WARN_BLOCK_DEPRECATED))
3945 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]);
3946
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003947 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003948 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003949 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003950
Cyril Bonté99ed3272010-01-24 23:29:44 +01003951 if (curproxy == &defproxy) {
3952 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956
Willy Tarreaube4653b2015-05-28 15:26:58 +02003957 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003958 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3959 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003962 }
3963
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003964 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003965 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003966 err_code |= warnif_cond_conflicts(rule->cond,
3967 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3968 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003969 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003970 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003971 struct switching_rule *rule;
3972
Willy Tarreaub099aca2008-10-12 17:26:37 +02003973 if (curproxy == &defproxy) {
3974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003977 }
3978
Willy Tarreau55ea7572007-06-17 19:56:27 +02003979 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003981
3982 if (*(args[1]) == 0) {
3983 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003986 }
3987
Willy Tarreauf51658d2014-04-23 01:21:56 +02003988 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3989 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3990 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3991 file, linenum, errmsg);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003995
Willy Tarreauf51658d2014-04-23 01:21:56 +02003996 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003997 }
3998
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003999 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02004000 rule->cond = cond;
4001 rule->be.name = strdup(args[1]);
4002 LIST_INIT(&rule->list);
4003 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4004 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004005 else if (strcmp(args[0], "use-server") == 0) {
4006 struct server_rule *rule;
4007
4008 if (curproxy == &defproxy) {
4009 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
4012 }
4013
4014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4015 err_code |= ERR_WARN;
4016
4017 if (*(args[1]) == 0) {
4018 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022
4023 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4024 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4025 file, linenum, args[0]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
4029
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004030 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4031 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4032 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004037 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004038
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004039 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004040 rule->cond = cond;
4041 rule->srv.name = strdup(args[1]);
4042 LIST_INIT(&rule->list);
4043 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4044 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4045 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004046 else if ((!strcmp(args[0], "force-persist")) ||
4047 (!strcmp(args[0], "ignore-persist"))) {
4048 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004049
4050 if (curproxy == &defproxy) {
4051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055
4056 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4057 err_code |= ERR_WARN;
4058
Willy Tarreauef6494c2010-01-28 17:12:36 +01004059 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004060 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4061 file, linenum, args[0]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004066 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4067 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4068 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004073 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4074 * where force-persist is applied.
4075 */
4076 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004077
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004078 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004079 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004080 if (!strcmp(args[0], "force-persist")) {
4081 rule->type = PERSIST_TYPE_FORCE;
4082 } else {
4083 rule->type = PERSIST_TYPE_IGNORE;
4084 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004085 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004086 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004087 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004088 else if (!strcmp(args[0], "stick-table")) {
4089 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004090 struct proxy *other;
4091
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004092 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004093 if (other) {
4094 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4095 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099
Emeric Brun32da3c42010-09-23 18:39:19 +02004100 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004101 curproxy->table.type = (unsigned int)-1;
4102 while (*args[myidx]) {
4103 const char *err;
4104
4105 if (strcmp(args[myidx], "size") == 0) {
4106 myidx++;
4107 if (!*(args[myidx])) {
4108 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4109 file, linenum, args[myidx-1]);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
4113 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4114 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4115 file, linenum, *err, args[myidx-1]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004119 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004120 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004121 else if (strcmp(args[myidx], "peers") == 0) {
4122 myidx++;
Godbach50523162013-12-11 19:48:57 +08004123 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004124 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4125 file, linenum, args[myidx-1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
Godbach50523162013-12-11 19:48:57 +08004128 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004129 curproxy->table.peers.name = strdup(args[myidx++]);
4130 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 else if (strcmp(args[myidx], "expire") == 0) {
4132 myidx++;
4133 if (!*(args[myidx])) {
4134 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4135 file, linenum, args[myidx-1]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
4139 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4140 if (err) {
4141 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4142 file, linenum, *err, args[myidx-1]);
4143 err_code |= ERR_ALERT | ERR_FATAL;
4144 goto out;
4145 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004146 if (val > INT_MAX) {
4147 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4148 file, linenum, val);
4149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
4151 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004153 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004154 }
4155 else if (strcmp(args[myidx], "nopurge") == 0) {
4156 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004157 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 }
4159 else if (strcmp(args[myidx], "type") == 0) {
4160 myidx++;
4161 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4162 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4163 file, linenum, args[myidx]);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004167 /* myidx already points to next arg */
4168 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004169 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004170 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004171 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004172
4173 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004174 nw = args[myidx];
4175 while (*nw) {
4176 /* the "store" keyword supports a comma-separated list */
4177 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004178 sa = NULL; /* store arg */
4179 while (*nw && *nw != ',') {
4180 if (*nw == '(') {
4181 *nw = 0;
4182 sa = ++nw;
4183 while (*nw != ')') {
4184 if (!*nw) {
4185 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4186 file, linenum, args[0], cw);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190 nw++;
4191 }
4192 *nw = '\0';
4193 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004194 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004195 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004196 if (*nw)
4197 *nw++ = '\0';
4198 type = stktable_get_data_type(cw);
4199 if (type < 0) {
4200 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4201 file, linenum, args[0], cw);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
Willy Tarreauac782882010-06-20 10:41:54 +02004205
4206 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4207 switch (err) {
4208 case PE_NONE: break;
4209 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004210 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4211 file, linenum, args[0], cw);
4212 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004213 break;
4214
4215 case PE_ARG_MISSING:
4216 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4217 file, linenum, args[0], cw);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220
4221 case PE_ARG_NOT_USED:
4222 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4223 file, linenum, args[0], cw);
4224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
4226
4227 default:
4228 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4229 file, linenum, args[0], cw);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004232 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004233 }
4234 myidx++;
4235 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004236 else {
4237 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4238 file, linenum, args[myidx]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004241 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004242 }
4243
4244 if (!curproxy->table.size) {
4245 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4246 file, linenum);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250
4251 if (curproxy->table.type == (unsigned int)-1) {
4252 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4253 file, linenum);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257 }
4258 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004259 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004260 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004261 int myidx = 0;
4262 const char *name = NULL;
4263 int flags;
4264
4265 if (curproxy == &defproxy) {
4266 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270
4271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4272 err_code |= ERR_WARN;
4273 goto out;
4274 }
4275
4276 myidx++;
4277 if ((strcmp(args[myidx], "store") == 0) ||
4278 (strcmp(args[myidx], "store-request") == 0)) {
4279 myidx++;
4280 flags = STK_IS_STORE;
4281 }
4282 else if (strcmp(args[myidx], "store-response") == 0) {
4283 myidx++;
4284 flags = STK_IS_STORE | STK_ON_RSP;
4285 }
4286 else if (strcmp(args[myidx], "match") == 0) {
4287 myidx++;
4288 flags = STK_IS_MATCH;
4289 }
4290 else if (strcmp(args[myidx], "on") == 0) {
4291 myidx++;
4292 flags = STK_IS_MATCH | STK_IS_STORE;
4293 }
4294 else {
4295 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299
4300 if (*(args[myidx]) == 0) {
4301 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
4304 }
4305
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004306 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004307 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004308 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004309 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313
4314 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004315 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4316 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4317 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004318 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004319 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004320 goto out;
4321 }
4322 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004323 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4324 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4325 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004326 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004327 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004328 goto out;
4329 }
4330 }
4331
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004332 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004333 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004334
Emeric Brunb982a3d2010-01-04 15:45:53 +01004335 if (strcmp(args[myidx], "table") == 0) {
4336 myidx++;
4337 name = args[myidx++];
4338 }
4339
Willy Tarreauef6494c2010-01-28 17:12:36 +01004340 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004341 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4342 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4343 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004344 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004345 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004346 goto out;
4347 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004348 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004349 else if (*(args[myidx])) {
4350 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4351 file, linenum, args[0], args[myidx]);
4352 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004353 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004354 goto out;
4355 }
Emeric Brun97679e72010-09-23 17:56:44 +02004356 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004357 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004358 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004359 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004360
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004361 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004362 rule->cond = cond;
4363 rule->expr = expr;
4364 rule->flags = flags;
4365 rule->table.name = name ? strdup(name) : NULL;
4366 LIST_INIT(&rule->list);
4367 if (flags & STK_ON_RSP)
4368 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4369 else
4370 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 else if (!strcmp(args[0], "stats")) {
4373 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4374 curproxy->uri_auth = NULL; /* we must detach from the default config */
4375
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004376 if (!*args[1]) {
4377 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004378 } else if (!strcmp(args[1], "admin")) {
4379 struct stats_admin_rule *rule;
4380
4381 if (curproxy == &defproxy) {
4382 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 }
4386
4387 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4388 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4389 err_code |= ERR_ALERT | ERR_ABORT;
4390 goto out;
4391 }
4392
4393 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4394 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4395 file, linenum, args[0], args[1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004399 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4400 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4401 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
4404 }
4405
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004406 err_code |= warnif_cond_conflicts(cond,
4407 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4408 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004409
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004410 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004411 rule->cond = cond;
4412 LIST_INIT(&rule->list);
4413 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 } else if (!strcmp(args[1], "uri")) {
4415 if (*(args[2]) == 0) {
4416 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4420 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_ALERT | ERR_ABORT;
4422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 }
4424 } else if (!strcmp(args[1], "realm")) {
4425 if (*(args[2]) == 0) {
4426 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004429 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4430 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_ALERT | ERR_ABORT;
4432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004434 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004435 unsigned interval;
4436
4437 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4438 if (err) {
4439 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4440 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004441 err_code |= ERR_ALERT | ERR_FATAL;
4442 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004443 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4444 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_ABORT;
4446 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004447 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004448 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004449 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004450
4451 if (curproxy == &defproxy) {
4452 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456
4457 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4458 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4459 err_code |= ERR_ALERT | ERR_ABORT;
4460 goto out;
4461 }
4462
Willy Tarreauff011f22011-01-06 17:51:27 +01004463 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004464 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004465 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4466 file, linenum, args[0]);
4467 err_code |= ERR_WARN;
4468 }
4469
Willy Tarreauff011f22011-01-06 17:51:27 +01004470 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004471
Willy Tarreauff011f22011-01-06 17:51:27 +01004472 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004473 err_code |= ERR_ALERT | ERR_ABORT;
4474 goto out;
4475 }
4476
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004477 err_code |= warnif_cond_conflicts(rule->cond,
4478 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4479 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004480 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004481
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 } else if (!strcmp(args[1], "auth")) {
4483 if (*(args[2]) == 0) {
4484 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004487 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4488 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= ERR_ALERT | ERR_ABORT;
4490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 }
4492 } else if (!strcmp(args[1], "scope")) {
4493 if (*(args[2]) == 0) {
4494 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4498 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_ABORT;
4500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 }
4502 } else if (!strcmp(args[1], "enable")) {
4503 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4504 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_ALERT | ERR_ABORT;
4506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004508 } else if (!strcmp(args[1], "hide-version")) {
4509 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4510 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004511 err_code |= ERR_ALERT | ERR_ABORT;
4512 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004513 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004514 } else if (!strcmp(args[1], "show-legends")) {
4515 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4516 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4517 err_code |= ERR_ALERT | ERR_ABORT;
4518 goto out;
4519 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004520 } else if (!strcmp(args[1], "show-node")) {
4521
4522 if (*args[2]) {
4523 int i;
4524 char c;
4525
4526 for (i=0; args[2][i]; i++) {
4527 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004528 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4529 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004530 break;
4531 }
4532
4533 if (!i || args[2][i]) {
4534 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4535 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4536 file, linenum, args[0], args[1]);
4537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
4540 }
4541
4542 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4543 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4544 err_code |= ERR_ALERT | ERR_ABORT;
4545 goto out;
4546 }
4547 } else if (!strcmp(args[1], "show-desc")) {
4548 char *desc = NULL;
4549
4550 if (*args[2]) {
4551 int i, len=0;
4552 char *d;
4553
Willy Tarreau348acfe2014-04-14 15:00:39 +02004554 for (i = 2; *args[i]; i++)
4555 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004556
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004557 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004558
Willy Tarreau348acfe2014-04-14 15:00:39 +02004559 d += snprintf(d, desc + len - d, "%s", args[2]);
4560 for (i = 3; *args[i]; i++)
4561 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004562 }
4563
4564 if (!*args[2] && !global.desc)
4565 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4566 file, linenum, args[1]);
4567 else {
4568 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4569 free(desc);
4570 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4571 err_code |= ERR_ALERT | ERR_ABORT;
4572 goto out;
4573 }
4574 free(desc);
4575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004577stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004578 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004579 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583 }
4584 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004585 int optnum;
4586
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004587 if (*(args[1]) == '\0') {
4588 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4589 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004593
4594 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4595 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004596 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4597 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4598 file, linenum, cfg_opts[optnum].name);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004602 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4603 goto out;
4604
Willy Tarreau93893792009-07-23 13:19:11 +02004605 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4606 err_code |= ERR_WARN;
4607 goto out;
4608 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004609
Willy Tarreau3842f002009-06-14 11:39:52 +02004610 curproxy->no_options &= ~cfg_opts[optnum].val;
4611 curproxy->options &= ~cfg_opts[optnum].val;
4612
4613 switch (kwm) {
4614 case KWM_STD:
4615 curproxy->options |= cfg_opts[optnum].val;
4616 break;
4617 case KWM_NO:
4618 curproxy->no_options |= cfg_opts[optnum].val;
4619 break;
4620 case KWM_DEF: /* already cleared */
4621 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004622 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004623
Willy Tarreau93893792009-07-23 13:19:11 +02004624 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004625 }
4626 }
4627
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004628 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4629 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004630 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4631 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4632 file, linenum, cfg_opts2[optnum].name);
4633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004636 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4637 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004638 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4639 err_code |= ERR_WARN;
4640 goto out;
4641 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004642
Willy Tarreau3842f002009-06-14 11:39:52 +02004643 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4644 curproxy->options2 &= ~cfg_opts2[optnum].val;
4645
4646 switch (kwm) {
4647 case KWM_STD:
4648 curproxy->options2 |= cfg_opts2[optnum].val;
4649 break;
4650 case KWM_NO:
4651 curproxy->no_options2 |= cfg_opts2[optnum].val;
4652 break;
4653 case KWM_DEF: /* already cleared */
4654 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004655 }
Willy Tarreau93893792009-07-23 13:19:11 +02004656 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004657 }
4658 }
4659
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004660 /* HTTP options override each other. They can be cancelled using
4661 * "no option xxx" which only switches to default mode if the mode
4662 * was this one (useful for cancelling options set in defaults
4663 * sections).
4664 */
4665 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004666 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4667 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004668 if (kwm == KWM_STD) {
4669 curproxy->options &= ~PR_O_HTTP_MODE;
4670 curproxy->options |= PR_O_HTTP_PCL;
4671 goto out;
4672 }
4673 else if (kwm == KWM_NO) {
4674 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4675 curproxy->options &= ~PR_O_HTTP_MODE;
4676 goto out;
4677 }
4678 }
4679 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004680 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4681 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004682 if (kwm == KWM_STD) {
4683 curproxy->options &= ~PR_O_HTTP_MODE;
4684 curproxy->options |= PR_O_HTTP_FCL;
4685 goto out;
4686 }
4687 else if (kwm == KWM_NO) {
4688 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4689 curproxy->options &= ~PR_O_HTTP_MODE;
4690 goto out;
4691 }
4692 }
4693 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004694 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4695 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004696 if (kwm == KWM_STD) {
4697 curproxy->options &= ~PR_O_HTTP_MODE;
4698 curproxy->options |= PR_O_HTTP_SCL;
4699 goto out;
4700 }
4701 else if (kwm == KWM_NO) {
4702 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4703 curproxy->options &= ~PR_O_HTTP_MODE;
4704 goto out;
4705 }
4706 }
4707 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004708 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4709 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004710 if (kwm == KWM_STD) {
4711 curproxy->options &= ~PR_O_HTTP_MODE;
4712 curproxy->options |= PR_O_HTTP_KAL;
4713 goto out;
4714 }
4715 else if (kwm == KWM_NO) {
4716 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4717 curproxy->options &= ~PR_O_HTTP_MODE;
4718 goto out;
4719 }
4720 }
4721 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004722 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4723 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004724 if (kwm == KWM_STD) {
4725 curproxy->options &= ~PR_O_HTTP_MODE;
4726 curproxy->options |= PR_O_HTTP_TUN;
4727 goto out;
4728 }
4729 else if (kwm == KWM_NO) {
4730 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4731 curproxy->options &= ~PR_O_HTTP_MODE;
4732 goto out;
4733 }
4734 }
4735
Joseph Lynch726ab712015-05-11 23:25:34 -07004736 /* Redispatch can take an integer argument that control when the
4737 * resispatch occurs. All values are relative to the retries option.
4738 * This can be cancelled using "no option xxx".
4739 */
4740 if (strcmp(args[1], "redispatch") == 0) {
4741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4742 err_code |= ERR_WARN;
4743 goto out;
4744 }
4745
4746 curproxy->no_options &= ~PR_O_REDISP;
4747 curproxy->options &= ~PR_O_REDISP;
4748
4749 switch (kwm) {
4750 case KWM_STD:
4751 curproxy->options |= PR_O_REDISP;
4752 curproxy->redispatch_after = -1;
4753 if(*args[2]) {
4754 curproxy->redispatch_after = atol(args[2]);
4755 }
4756 break;
4757 case KWM_NO:
4758 curproxy->no_options |= PR_O_REDISP;
4759 curproxy->redispatch_after = 0;
4760 break;
4761 case KWM_DEF: /* already cleared */
4762 break;
4763 }
4764 goto out;
4765 }
4766
Willy Tarreau3842f002009-06-14 11:39:52 +02004767 if (kwm != KWM_STD) {
4768 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004769 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004772 }
4773
Emeric Brun3a058f32009-06-30 18:26:00 +02004774 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004775 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004777 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004778 if (*(args[2]) != '\0') {
4779 if (!strcmp(args[2], "clf")) {
4780 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004781 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004782 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004783 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004786 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004787 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4788 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004789 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004790 if (curproxy->conf.logformat_string != default_http_log_format &&
4791 curproxy->conf.logformat_string != default_tcp_log_format &&
4792 curproxy->conf.logformat_string != clf_http_log_format)
4793 free(curproxy->conf.logformat_string);
4794 curproxy->conf.logformat_string = logformat;
4795
4796 free(curproxy->conf.lfs_file);
4797 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4798 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004799 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004800 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004802 if (curproxy->conf.logformat_string != default_http_log_format &&
4803 curproxy->conf.logformat_string != default_tcp_log_format &&
4804 curproxy->conf.logformat_string != clf_http_log_format)
4805 free(curproxy->conf.logformat_string);
4806 curproxy->conf.logformat_string = default_tcp_log_format;
4807
4808 free(curproxy->conf.lfs_file);
4809 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4810 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004811
4812 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4813 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004816 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004817 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004818 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004819
William Lallemanddf1425a2015-04-28 20:17:49 +02004820 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4821 goto out;
4822
Willy Tarreau13943ab2006-12-31 00:24:10 +01004823 if (curproxy->cap & PR_CAP_FE)
4824 curproxy->options |= PR_O_TCP_CLI_KA;
4825 if (curproxy->cap & PR_CAP_BE)
4826 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 }
4828 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004830 err_code |= ERR_WARN;
4831
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004833 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004834 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004835 curproxy->options2 &= ~PR_O2_CHK_ANY;
4836 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 if (!*args[2]) { /* no argument */
4838 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4839 curproxy->check_len = strlen(DEF_CHECK_REQ);
4840 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004841 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004842 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004844 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004846 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 if (*args[4])
4848 reqlen += strlen(args[4]);
4849 else
4850 reqlen += strlen("HTTP/1.0");
4851
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004852 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004854 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004856 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4857 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004858 }
4859 else if (!strcmp(args[1], "ssl-hello-chk")) {
4860 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004861 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004863
Willy Tarreaua534fea2008-08-03 12:19:50 +02004864 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004865 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004866 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004867 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004868
4869 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
Willy Tarreau23677902007-05-08 23:50:35 +02004872 else if (!strcmp(args[1], "smtpchk")) {
4873 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004874 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004875 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004876 curproxy->options2 &= ~PR_O2_CHK_ANY;
4877 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004878
4879 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4880 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4881 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4882 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4883 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4884 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004885 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004886 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4887 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4888 } else {
4889 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4890 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4891 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4892 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4893 }
4894 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004895 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4896 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004897 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004898 else if (!strcmp(args[1], "pgsql-check")) {
4899 /* use PostgreSQL request to check servers' health */
4900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4901 err_code |= ERR_WARN;
4902
4903 free(curproxy->check_req);
4904 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004905 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004906 curproxy->options2 |= PR_O2_PGSQL_CHK;
4907
4908 if (*(args[2])) {
4909 int cur_arg = 2;
4910
4911 while (*(args[cur_arg])) {
4912 if (strcmp(args[cur_arg], "user") == 0) {
4913 char * packet;
4914 uint32_t packet_len;
4915 uint32_t pv;
4916
4917 /* suboption header - needs additional argument for it */
4918 if (*(args[cur_arg+1]) == 0) {
4919 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4920 file, linenum, args[0], args[1], args[cur_arg]);
4921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923 }
4924
4925 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4926 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4927 pv = htonl(0x30000); /* protocol version 3.0 */
4928
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004929 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004930
4931 memcpy(packet + 4, &pv, 4);
4932
4933 /* copy "user" */
4934 memcpy(packet + 8, "user", 4);
4935
4936 /* copy username */
4937 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4938
4939 free(curproxy->check_req);
4940 curproxy->check_req = packet;
4941 curproxy->check_len = packet_len;
4942
4943 packet_len = htonl(packet_len);
4944 memcpy(packet, &packet_len, 4);
4945 cur_arg += 2;
4946 } else {
4947 /* unknown suboption - catchall */
4948 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4949 file, linenum, args[0], args[1]);
4950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
4953 } /* end while loop */
4954 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004955 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4956 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004957 }
4958
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004959 else if (!strcmp(args[1], "redis-check")) {
4960 /* use REDIS PING request to check servers' health */
4961 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4962 err_code |= ERR_WARN;
4963
4964 free(curproxy->check_req);
4965 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004966 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004967 curproxy->options2 |= PR_O2_REDIS_CHK;
4968
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004969 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004970 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4971 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004972
4973 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4974 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004975 }
4976
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004977 else if (!strcmp(args[1], "mysql-check")) {
4978 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004979 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4980 err_code |= ERR_WARN;
4981
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004982 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004983 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004984 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004985 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004986
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004987 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004988 * const char mysql40_client_auth_pkt[] = {
4989 * "\x0e\x00\x00" // packet length
4990 * "\x01" // packet number
4991 * "\x00\x00" // client capabilities
4992 * "\x00\x00\x01" // max packet
4993 * "haproxy\x00" // username (null terminated string)
4994 * "\x00" // filler (always 0x00)
4995 * "\x01\x00\x00" // packet length
4996 * "\x00" // packet number
4997 * "\x01" // COM_QUIT command
4998 * };
4999 */
5000
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005001 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5002 * const char mysql41_client_auth_pkt[] = {
5003 * "\x0e\x00\x00\" // packet length
5004 * "\x01" // packet number
5005 * "\x00\x00\x00\x00" // client capabilities
5006 * "\x00\x00\x00\x01" // max packet
5007 * "\x21" // character set (UTF-8)
5008 * char[23] // All zeroes
5009 * "haproxy\x00" // username (null terminated string)
5010 * "\x00" // filler (always 0x00)
5011 * "\x01\x00\x00" // packet length
5012 * "\x00" // packet number
5013 * "\x01" // COM_QUIT command
5014 * };
5015 */
5016
5017
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005018 if (*(args[2])) {
5019 int cur_arg = 2;
5020
5021 while (*(args[cur_arg])) {
5022 if (strcmp(args[cur_arg], "user") == 0) {
5023 char *mysqluser;
5024 int packetlen, reqlen, userlen;
5025
5026 /* suboption header - needs additional argument for it */
5027 if (*(args[cur_arg+1]) == 0) {
5028 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5029 file, linenum, args[0], args[1], args[cur_arg]);
5030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032 }
5033 mysqluser = args[cur_arg + 1];
5034 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005035
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005036 if (*(args[cur_arg+2])) {
5037 if (!strcmp(args[cur_arg+2], "post-41")) {
5038 packetlen = userlen + 7 + 27;
5039 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005040
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005041 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005042 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005043 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005044
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005045 snprintf(curproxy->check_req, 4, "%c%c%c",
5046 ((unsigned char) packetlen & 0xff),
5047 ((unsigned char) (packetlen >> 8) & 0xff),
5048 ((unsigned char) (packetlen >> 16) & 0xff));
5049
5050 curproxy->check_req[3] = 1;
5051 curproxy->check_req[5] = 130;
5052 curproxy->check_req[11] = 1;
5053 curproxy->check_req[12] = 33;
5054 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5055 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5056 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5057 cur_arg += 3;
5058 } else {
5059 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
5062 }
5063 } else {
5064 packetlen = userlen + 7;
5065 reqlen = packetlen + 9;
5066
5067 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005068 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005069 curproxy->check_len = reqlen;
5070
5071 snprintf(curproxy->check_req, 4, "%c%c%c",
5072 ((unsigned char) packetlen & 0xff),
5073 ((unsigned char) (packetlen >> 8) & 0xff),
5074 ((unsigned char) (packetlen >> 16) & 0xff));
5075
5076 curproxy->check_req[3] = 1;
5077 curproxy->check_req[5] = 128;
5078 curproxy->check_req[8] = 1;
5079 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5080 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5081 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5082 cur_arg += 2;
5083 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005084 } else {
5085 /* unknown suboption - catchall */
5086 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5087 file, linenum, args[0], args[1]);
5088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
5090 }
5091 } /* end while loop */
5092 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005093 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005094 else if (!strcmp(args[1], "ldap-check")) {
5095 /* use LDAP request to check servers' health */
5096 free(curproxy->check_req);
5097 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005098 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005099 curproxy->options2 |= PR_O2_LDAP_CHK;
5100
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005101 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005102 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5103 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005104 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5105 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005106 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005107 else if (!strcmp(args[1], "tcp-check")) {
5108 /* use raw TCPCHK send/expect to check servers' health */
5109 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5110 err_code |= ERR_WARN;
5111
5112 free(curproxy->check_req);
5113 curproxy->check_req = NULL;
5114 curproxy->options2 &= ~PR_O2_CHK_ANY;
5115 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005116 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5117 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005118 }
Simon Horman98637e52014-06-20 12:30:16 +09005119 else if (!strcmp(args[1], "external-check")) {
5120 /* excute an external command to check servers' health */
5121 free(curproxy->check_req);
5122 curproxy->check_req = NULL;
5123 curproxy->options2 &= ~PR_O2_CHK_ANY;
5124 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005125 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5126 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005127 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005128 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005129 int cur_arg;
5130
5131 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5132 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005133 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005134
Willy Tarreau87cf5142011-08-19 22:57:24 +02005135 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005136
5137 free(curproxy->fwdfor_hdr_name);
5138 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5139 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5140
5141 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5142 cur_arg = 2;
5143 while (*(args[cur_arg])) {
5144 if (!strcmp(args[cur_arg], "except")) {
5145 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005146 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005147 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5148 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005151 }
5152 /* flush useless bits */
5153 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005154 cur_arg += 2;
5155 } else if (!strcmp(args[cur_arg], "header")) {
5156 /* suboption header - needs additional argument for it */
5157 if (*(args[cur_arg+1]) == 0) {
5158 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5159 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005162 }
5163 free(curproxy->fwdfor_hdr_name);
5164 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5165 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5166 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005167 } else if (!strcmp(args[cur_arg], "if-none")) {
5168 curproxy->options &= ~PR_O_FF_ALWAYS;
5169 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005170 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005171 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005172 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005173 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005176 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005177 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005178 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005179 else if (!strcmp(args[1], "originalto")) {
5180 int cur_arg;
5181
5182 /* insert x-original-to field, but not for the IP address listed as an except.
5183 * set default options (ie: bitfield, header name, etc)
5184 */
5185
5186 curproxy->options |= PR_O_ORGTO;
5187
5188 free(curproxy->orgto_hdr_name);
5189 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5190 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5191
Willy Tarreau87cf5142011-08-19 22:57:24 +02005192 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005193 cur_arg = 2;
5194 while (*(args[cur_arg])) {
5195 if (!strcmp(args[cur_arg], "except")) {
5196 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005197 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 +02005198 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5199 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005202 }
5203 /* flush useless bits */
5204 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5205 cur_arg += 2;
5206 } else if (!strcmp(args[cur_arg], "header")) {
5207 /* suboption header - needs additional argument for it */
5208 if (*(args[cur_arg+1]) == 0) {
5209 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5210 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005213 }
5214 free(curproxy->orgto_hdr_name);
5215 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5216 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5217 cur_arg += 2;
5218 } else {
5219 /* unknown suboption - catchall */
5220 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5221 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005224 }
5225 } /* end while loop */
5226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 else {
5228 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 }
Willy Tarreau93893792009-07-23 13:19:11 +02005232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005234 else if (!strcmp(args[0], "default_backend")) {
5235 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005236 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005237
5238 if (*(args[1]) == 0) {
5239 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005242 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005243 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005244 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005245
5246 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5247 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005250 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005252
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005253 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5254 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 +01005255 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 /* enable reconnections to dispatch */
5258 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005259
5260 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005263 else if (!strcmp(args[0], "http-reuse")) {
5264 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5265 err_code |= ERR_WARN;
5266
5267 if (strcmp(args[1], "never") == 0) {
5268 /* enable a graceful server shutdown on an HTTP 404 response */
5269 curproxy->options &= ~PR_O_REUSE_MASK;
5270 curproxy->options |= PR_O_REUSE_NEVR;
5271 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5272 goto out;
5273 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005274 else if (strcmp(args[1], "safe") == 0) {
5275 /* enable a graceful server shutdown on an HTTP 404 response */
5276 curproxy->options &= ~PR_O_REUSE_MASK;
5277 curproxy->options |= PR_O_REUSE_SAFE;
5278 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5279 goto out;
5280 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005281 else if (strcmp(args[1], "aggressive") == 0) {
5282 curproxy->options &= ~PR_O_REUSE_MASK;
5283 curproxy->options |= PR_O_REUSE_AGGR;
5284 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5285 goto out;
5286 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005287 else if (strcmp(args[1], "always") == 0) {
5288 /* enable a graceful server shutdown on an HTTP 404 response */
5289 curproxy->options &= ~PR_O_REUSE_MASK;
5290 curproxy->options |= PR_O_REUSE_ALWS;
5291 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5292 goto out;
5293 }
5294 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005295 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
5298 }
5299 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005300 else if (!strcmp(args[0], "http-check")) {
5301 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005302 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005303
5304 if (strcmp(args[1], "disable-on-404") == 0) {
5305 /* enable a graceful server shutdown on an HTTP 404 response */
5306 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005307 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5308 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005309 }
Willy Tarreauef781042010-01-27 11:53:01 +01005310 else if (strcmp(args[1], "send-state") == 0) {
5311 /* enable emission of the apparent state of a server in HTTP checks */
5312 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005313 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5314 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005315 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005316 else if (strcmp(args[1], "expect") == 0) {
5317 const char *ptr_arg;
5318 int cur_arg;
5319
5320 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5321 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
5325
5326 cur_arg = 2;
5327 /* consider exclamation marks, sole or at the beginning of a word */
5328 while (*(ptr_arg = args[cur_arg])) {
5329 while (*ptr_arg == '!') {
5330 curproxy->options2 ^= PR_O2_EXP_INV;
5331 ptr_arg++;
5332 }
5333 if (*ptr_arg)
5334 break;
5335 cur_arg++;
5336 }
5337 /* now ptr_arg points to the beginning of a word past any possible
5338 * exclamation mark, and cur_arg is the argument which holds this word.
5339 */
5340 if (strcmp(ptr_arg, "status") == 0) {
5341 if (!*(args[cur_arg + 1])) {
5342 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5343 file, linenum, args[0], args[1], ptr_arg);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005348 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005349 curproxy->expect_str = strdup(args[cur_arg + 1]);
5350 }
5351 else if (strcmp(ptr_arg, "string") == 0) {
5352 if (!*(args[cur_arg + 1])) {
5353 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5354 file, linenum, args[0], args[1], ptr_arg);
5355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357 }
5358 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005359 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005360 curproxy->expect_str = strdup(args[cur_arg + 1]);
5361 }
5362 else if (strcmp(ptr_arg, "rstatus") == 0) {
5363 if (!*(args[cur_arg + 1])) {
5364 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5365 file, linenum, args[0], args[1], ptr_arg);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005370 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005371 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005372 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005373 free(curproxy->expect_regex);
5374 curproxy->expect_regex = NULL;
5375 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005376 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005377 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5378 error = NULL;
5379 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5380 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5381 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5382 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
5385 }
5386 }
5387 else if (strcmp(ptr_arg, "rstring") == 0) {
5388 if (!*(args[cur_arg + 1])) {
5389 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5390 file, linenum, args[0], args[1], ptr_arg);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
5393 }
5394 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005395 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005396 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005397 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005398 free(curproxy->expect_regex);
5399 curproxy->expect_regex = NULL;
5400 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005401 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005402 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5403 error = NULL;
5404 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5405 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5406 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5407 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411 }
5412 else {
5413 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5414 file, linenum, args[0], args[1], ptr_arg);
5415 err_code |= ERR_ALERT | ERR_FATAL;
5416 goto out;
5417 }
5418 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005419 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005420 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 +02005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005423 }
5424 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005425 else if (!strcmp(args[0], "tcp-check")) {
5426 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5427 err_code |= ERR_WARN;
5428
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005429 if (strcmp(args[1], "comment") == 0) {
5430 int cur_arg;
5431 struct tcpcheck_rule *tcpcheck;
5432
5433 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005434 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005435 tcpcheck->action = TCPCHK_ACT_COMMENT;
5436
5437 if (!*args[cur_arg + 1]) {
5438 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5439 file, linenum, args[cur_arg]);
5440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
5442 }
5443
5444 tcpcheck->comment = strdup(args[cur_arg + 1]);
5445
5446 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005447 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5448 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005449 }
5450 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005451 const char *ptr_arg;
5452 int cur_arg;
5453 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005454
5455 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005456 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5457 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5458 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5459 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5460 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005461
Willy Tarreau5581c272015-05-13 12:24:53 +02005462 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5463 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5464 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5465 file, linenum);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005468 }
5469
5470 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005471 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005472 tcpcheck->action = TCPCHK_ACT_CONNECT;
5473
5474 /* parsing each parameters to fill up the rule */
5475 while (*(ptr_arg = args[cur_arg])) {
5476 /* tcp port */
5477 if (strcmp(args[cur_arg], "port") == 0) {
5478 if ( (atol(args[cur_arg + 1]) > 65535) ||
5479 (atol(args[cur_arg + 1]) < 1) ){
5480 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5481 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
5484 }
5485 tcpcheck->port = atol(args[cur_arg + 1]);
5486 cur_arg += 2;
5487 }
5488 /* send proxy protocol */
5489 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5490 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5491 cur_arg++;
5492 }
5493#ifdef USE_OPENSSL
5494 else if (strcmp(args[cur_arg], "ssl") == 0) {
5495 curproxy->options |= PR_O_TCPCHK_SSL;
5496 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5497 cur_arg++;
5498 }
5499#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005500 /* comment for this tcpcheck line */
5501 else if (strcmp(args[cur_arg], "comment") == 0) {
5502 if (!*args[cur_arg + 1]) {
5503 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5504 file, linenum, args[cur_arg]);
5505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
5507 }
5508 tcpcheck->comment = strdup(args[cur_arg + 1]);
5509 cur_arg += 2;
5510 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005511 else {
5512#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005513 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 +01005514#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005515 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 +01005516#endif /* USE_OPENSSL */
5517 file, linenum, args[0], args[1], args[cur_arg]);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521
5522 }
5523
5524 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5525 }
5526 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005527 if (! *(args[2]) ) {
5528 /* SEND string expected */
5529 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5530 file, linenum, args[0], args[1], args[2]);
5531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 } else {
5534 struct tcpcheck_rule *tcpcheck;
5535
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005536 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005537
5538 tcpcheck->action = TCPCHK_ACT_SEND;
5539 tcpcheck->string_len = strlen(args[2]);
5540 tcpcheck->string = strdup(args[2]);
5541 tcpcheck->expect_regex = NULL;
5542
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005543 /* comment for this tcpcheck line */
5544 if (strcmp(args[3], "comment") == 0) {
5545 if (!*args[4]) {
5546 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5547 file, linenum, args[3]);
5548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
5550 }
5551 tcpcheck->comment = strdup(args[4]);
5552 }
5553
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005554 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5555 }
5556 }
5557 else if (strcmp(args[1], "send-binary") == 0) {
5558 if (! *(args[2]) ) {
5559 /* SEND binary string expected */
5560 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5561 file, linenum, args[0], args[1], args[2]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 } else {
5565 struct tcpcheck_rule *tcpcheck;
5566 char *err = NULL;
5567
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005568 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005569
5570 tcpcheck->action = TCPCHK_ACT_SEND;
5571 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5572 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5573 file, linenum, args[0], args[1], args[2], err);
5574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 }
5577 tcpcheck->expect_regex = NULL;
5578
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005579 /* comment for this tcpcheck line */
5580 if (strcmp(args[3], "comment") == 0) {
5581 if (!*args[4]) {
5582 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5583 file, linenum, args[3]);
5584 err_code |= ERR_ALERT | ERR_FATAL;
5585 goto out;
5586 }
5587 tcpcheck->comment = strdup(args[4]);
5588 }
5589
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005590 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5591 }
5592 }
5593 else if (strcmp(args[1], "expect") == 0) {
5594 const char *ptr_arg;
5595 int cur_arg;
5596 int inverse = 0;
5597
5598 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5599 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
5602 }
5603
5604 cur_arg = 2;
5605 /* consider exclamation marks, sole or at the beginning of a word */
5606 while (*(ptr_arg = args[cur_arg])) {
5607 while (*ptr_arg == '!') {
5608 inverse = !inverse;
5609 ptr_arg++;
5610 }
5611 if (*ptr_arg)
5612 break;
5613 cur_arg++;
5614 }
5615 /* now ptr_arg points to the beginning of a word past any possible
5616 * exclamation mark, and cur_arg is the argument which holds this word.
5617 */
5618 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005619 struct tcpcheck_rule *tcpcheck;
5620 char *err = NULL;
5621
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005622 if (!*(args[cur_arg + 1])) {
5623 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5624 file, linenum, args[0], args[1], ptr_arg);
5625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005628
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005629 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005630
5631 tcpcheck->action = TCPCHK_ACT_EXPECT;
5632 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5633 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5634 file, linenum, args[0], args[1], args[2], err);
5635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
5637 }
5638 tcpcheck->expect_regex = NULL;
5639 tcpcheck->inverse = inverse;
5640
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005641 /* tcpcheck comment */
5642 cur_arg += 2;
5643 if (strcmp(args[cur_arg], "comment") == 0) {
5644 if (!*args[cur_arg + 1]) {
5645 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5646 file, linenum, args[cur_arg + 1]);
5647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
5650 tcpcheck->comment = strdup(args[cur_arg + 1]);
5651 }
5652
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005653 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5654 }
5655 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005656 struct tcpcheck_rule *tcpcheck;
5657
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005658 if (!*(args[cur_arg + 1])) {
5659 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5660 file, linenum, args[0], args[1], ptr_arg);
5661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
5663 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005664
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005665 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005666
5667 tcpcheck->action = TCPCHK_ACT_EXPECT;
5668 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5669 tcpcheck->string = strdup(args[cur_arg + 1]);
5670 tcpcheck->expect_regex = NULL;
5671 tcpcheck->inverse = inverse;
5672
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005673 /* tcpcheck comment */
5674 cur_arg += 2;
5675 if (strcmp(args[cur_arg], "comment") == 0) {
5676 if (!*args[cur_arg + 1]) {
5677 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5678 file, linenum, args[cur_arg + 1]);
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
5681 }
5682 tcpcheck->comment = strdup(args[cur_arg + 1]);
5683 }
5684
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005685 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5686 }
5687 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005688 struct tcpcheck_rule *tcpcheck;
5689
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005690 if (!*(args[cur_arg + 1])) {
5691 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5692 file, linenum, args[0], args[1], ptr_arg);
5693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
5695 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005696
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005697 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005698
5699 tcpcheck->action = TCPCHK_ACT_EXPECT;
5700 tcpcheck->string_len = 0;
5701 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005702 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5703 error = NULL;
5704 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5705 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5706 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5707 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
5710 }
5711 tcpcheck->inverse = inverse;
5712
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005713 /* tcpcheck comment */
5714 cur_arg += 2;
5715 if (strcmp(args[cur_arg], "comment") == 0) {
5716 if (!*args[cur_arg + 1]) {
5717 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5718 file, linenum, args[cur_arg + 1]);
5719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
5721 }
5722 tcpcheck->comment = strdup(args[cur_arg + 1]);
5723 }
5724
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005725 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5726 }
5727 else {
5728 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5729 file, linenum, args[0], args[1], ptr_arg);
5730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
5732 }
5733 }
5734 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005735 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
5738 }
5739 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005740 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005741 if (curproxy == &defproxy) {
5742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005745 }
5746
Willy Tarreaub80c2302007-11-30 20:51:32 +01005747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005749
5750 if (strcmp(args[1], "fail") == 0) {
5751 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005752 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005753 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5754 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005757 }
5758
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005759 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5760 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5761 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005764 }
5765 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5766 }
5767 else {
5768 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005771 }
5772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773#ifdef TPROXY
5774 else if (!strcmp(args[0], "transparent")) {
5775 /* enable transparent proxy connections */
5776 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005777 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 }
5780#endif
5781 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005782 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005783 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005784
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 if (*(args[1]) == 0) {
5786 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005787 err_code |= ERR_ALERT | ERR_FATAL;
5788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 }
5790 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005791 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005794 else if (!strcmp(args[0], "backlog")) { /* backlog */
5795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005797
5798 if (*(args[1]) == 0) {
5799 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005802 }
5803 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005804 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5805 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005806 }
Willy Tarreau86034312006-12-29 00:10:33 +01005807 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005810
Willy Tarreau86034312006-12-29 00:10:33 +01005811 if (*(args[1]) == 0) {
5812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005813 err_code |= ERR_ALERT | ERR_FATAL;
5814 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005815 }
5816 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005817 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5818 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5821 if (*(args[1]) == 0) {
5822 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005826 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5827 if (err) {
5828 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5829 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005832 }
5833 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005834 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 }
5837 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005838 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005839 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005840 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005841
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 if (curproxy == &defproxy) {
5843 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005847 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005848 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005849
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005850 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005851 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005852 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005853 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005854 goto out;
5855 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005856
5857 proto = protocol_by_family(sk->ss_family);
5858 if (!proto || !proto->connect) {
5859 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5860 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005861 err_code |= ERR_ALERT | ERR_FATAL;
5862 goto out;
5863 }
5864
5865 if (port1 != port2) {
5866 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5867 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005871
5872 if (!port1) {
5873 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5874 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005878
William Lallemanddf1425a2015-04-28 20:17:49 +02005879 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5880 goto out;
5881
Willy Tarreaud5191e72010-02-09 20:50:45 +01005882 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005883 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 }
5885 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005886 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005887 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005888
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005889 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5890 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005895 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005896 /**
5897 * The syntax for hash-type config element is
5898 * hash-type {map-based|consistent} [[<algo>] avalanche]
5899 *
5900 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5901 */
5902 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005903
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005904 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5905 err_code |= ERR_WARN;
5906
5907 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005908 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5909 }
5910 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005911 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5912 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005913 else if (strcmp(args[1], "avalanche") == 0) {
5914 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]);
5915 err_code |= ERR_ALERT | ERR_FATAL;
5916 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005917 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005918 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005919 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005920 err_code |= ERR_ALERT | ERR_FATAL;
5921 goto out;
5922 }
Bhaskar98634f02013-10-29 23:30:51 -04005923
5924 /* set the hash function to use */
5925 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005926 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005927 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005928
5929 /* if consistent with no argument, then avalanche modifier is also applied */
5930 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5931 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005932 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005933 /* set the hash function */
5934 if (!strcmp(args[2], "sdbm")) {
5935 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5936 }
5937 else if (!strcmp(args[2], "djb2")) {
5938 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005939 }
5940 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005941 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005942 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005943 else if (!strcmp(args[2], "crc32")) {
5944 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5945 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005946 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005947 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 -05005948 err_code |= ERR_ALERT | ERR_FATAL;
5949 goto out;
5950 }
5951
5952 /* set the hash modifier */
5953 if (!strcmp(args[3], "avalanche")) {
5954 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5955 }
5956 else if (*args[3]) {
5957 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5958 err_code |= ERR_ALERT | ERR_FATAL;
5959 goto out;
5960 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005961 }
William Lallemanda73203e2012-03-12 12:48:57 +01005962 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005963 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5964 if (*(args[1]) == 0) {
5965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5966 err_code |= ERR_ALERT | ERR_FATAL;
5967 goto out;
5968 }
5969 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5970 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5971 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
5975 }
William Lallemanda73203e2012-03-12 12:48:57 +01005976 else if (strcmp(args[0], "unique-id-format") == 0) {
5977 if (!*(args[1])) {
5978 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
William Lallemand3203ff42012-11-11 17:30:56 +01005982 if (*(args[2])) {
5983 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5984 err_code |= ERR_ALERT | ERR_FATAL;
5985 goto out;
5986 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005987 free(curproxy->conf.uniqueid_format_string);
5988 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005989
Willy Tarreau62a61232013-04-12 18:13:46 +02005990 free(curproxy->conf.uif_file);
5991 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5992 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005993 }
William Lallemanda73203e2012-03-12 12:48:57 +01005994
5995 else if (strcmp(args[0], "unique-id-header") == 0) {
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 free(curproxy->header_unique_id);
6002 curproxy->header_unique_id = strdup(args[1]);
6003 }
6004
William Lallemand723b73a2012-02-08 16:37:49 +01006005 else if (strcmp(args[0], "log-format") == 0) {
6006 if (!*(args[1])) {
6007 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6008 err_code |= ERR_ALERT | ERR_FATAL;
6009 goto out;
6010 }
William Lallemand3203ff42012-11-11 17:30:56 +01006011 if (*(args[2])) {
6012 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6013 err_code |= ERR_ALERT | ERR_FATAL;
6014 goto out;
6015 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006016
Willy Tarreau62a61232013-04-12 18:13:46 +02006017 if (curproxy->conf.logformat_string != default_http_log_format &&
6018 curproxy->conf.logformat_string != default_tcp_log_format &&
6019 curproxy->conf.logformat_string != clf_http_log_format)
6020 free(curproxy->conf.logformat_string);
6021 curproxy->conf.logformat_string = strdup(args[1]);
6022
6023 free(curproxy->conf.lfs_file);
6024 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6025 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006026
6027 /* get a chance to improve log-format error reporting by
6028 * reporting the correct line-number when possible.
6029 */
6030 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6031 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6032 file, linenum, curproxy->id);
6033 err_code |= ERR_WARN;
6034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006036 else if (!strcmp(args[0], "log-format-sd")) {
6037 if (!*(args[1])) {
6038 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6039 err_code |= ERR_ALERT | ERR_FATAL;
6040 goto out;
6041 }
6042 if (*(args[2])) {
6043 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6044 err_code |= ERR_ALERT | ERR_FATAL;
6045 goto out;
6046 }
6047
6048 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6049 free(curproxy->conf.logformat_sd_string);
6050 curproxy->conf.logformat_sd_string = strdup(args[1]);
6051
6052 free(curproxy->conf.lfsd_file);
6053 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6054 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6055
6056 /* get a chance to improve log-format-sd error reporting by
6057 * reporting the correct line-number when possible.
6058 */
6059 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6060 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6061 file, linenum, curproxy->id);
6062 err_code |= ERR_WARN;
6063 }
6064 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006065 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6066 if (*(args[1]) == 0) {
6067 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006071 chunk_destroy(&curproxy->log_tag);
6072 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006073 }
William Lallemand0f99e342011-10-12 17:50:54 +02006074 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6075 /* delete previous herited or defined syslog servers */
6076 struct logsrv *back;
6077
6078 if (*(args[1]) != 0) {
6079 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
6082 }
6083
William Lallemand723b73a2012-02-08 16:37:49 +01006084 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6085 LIST_DEL(&tmplogsrv->list);
6086 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006087 }
6088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006090 struct logsrv *logsrv;
6091
Willy Tarreaubaaee002006-06-26 02:48:02 +02006092 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006093 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006094 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006095 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006096 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006097 LIST_INIT(&node->list);
6098 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006100 }
6101 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006102 struct sockaddr_storage *sk;
6103 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006104 int arg = 0;
6105 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006106
Vincent Bernat02779b62016-04-03 13:48:43 +02006107 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108
Willy Tarreau18324f52014-06-27 18:10:07 +02006109 /* just after the address, a length may be specified */
6110 if (strcmp(args[arg+2], "len") == 0) {
6111 len = atoi(args[arg+3]);
6112 if (len < 80 || len > 65535) {
6113 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6114 file, linenum, args[arg+3]);
6115 err_code |= ERR_ALERT | ERR_FATAL;
6116 goto out;
6117 }
6118 logsrv->maxlen = len;
6119
6120 /* skip these two args */
6121 arg += 2;
6122 }
6123 else
6124 logsrv->maxlen = MAX_SYSLOG_LEN;
6125
6126 if (logsrv->maxlen > global.max_syslog_len) {
6127 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006128 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6129 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6130 logline = my_realloc2(logline, global.max_syslog_len + 1);
6131 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006132 }
6133
Dragan Dosen1322d092015-09-22 16:05:32 +02006134 /* after the length, a format may be specified */
6135 if (strcmp(args[arg+2], "format") == 0) {
6136 logsrv->format = get_log_format(args[arg+3]);
6137 if (logsrv->format < 0) {
6138 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6139 err_code |= ERR_ALERT | ERR_FATAL;
6140 goto out;
6141 }
6142
6143 /* skip these two args */
6144 arg += 2;
6145 }
6146
William Lallemanddf1425a2015-04-28 20:17:49 +02006147 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6148 goto out;
6149
Willy Tarreau18324f52014-06-27 18:10:07 +02006150 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006151 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006152 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
6155
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
6157
William Lallemand0f99e342011-10-12 17:50:54 +02006158 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006159 if (*(args[arg+3])) {
6160 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006161 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006162 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006163 err_code |= ERR_ALERT | ERR_FATAL;
6164 goto out;
6165
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 }
6167 }
6168
William Lallemand0f99e342011-10-12 17:50:54 +02006169 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006170 if (*(args[arg+4])) {
6171 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006172 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006173 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006174 err_code |= ERR_ALERT | ERR_FATAL;
6175 goto out;
6176
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006177 }
6178 }
6179
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006180 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006181 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006182 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006183 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006184 goto out;
6185 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006186
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006187 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006188
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006189 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006190 if (port1 != port2) {
6191 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6192 file, linenum, args[0], args[1]);
6193 err_code |= ERR_ALERT | ERR_FATAL;
6194 goto out;
6195 }
6196
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006197 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006198 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 }
William Lallemand0f99e342011-10-12 17:50:54 +02006200
6201 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202 }
6203 else {
6204 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6205 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006206 err_code |= ERR_ALERT | ERR_FATAL;
6207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208 }
6209 }
6210 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006211 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006212 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006213 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006214 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006215
Willy Tarreau977b8e42006-12-29 14:19:17 +01006216 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006217 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006218
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006220 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6221 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006222 err_code |= ERR_ALERT | ERR_FATAL;
6223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006224 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006225
6226 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006227 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6228 free(curproxy->conn_src.iface_name);
6229 curproxy->conn_src.iface_name = NULL;
6230 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006231
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006232 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006233 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006234 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006235 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006236 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006237 goto out;
6238 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006239
6240 proto = protocol_by_family(sk->ss_family);
6241 if (!proto || !proto->connect) {
6242 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006243 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006244 err_code |= ERR_ALERT | ERR_FATAL;
6245 goto out;
6246 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006247
6248 if (port1 != port2) {
6249 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6250 file, linenum, args[0], args[1]);
6251 err_code |= ERR_ALERT | ERR_FATAL;
6252 goto out;
6253 }
6254
Willy Tarreauef9a3602012-12-08 22:29:20 +01006255 curproxy->conn_src.source_addr = *sk;
6256 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006257
6258 cur_arg = 2;
6259 while (*(args[cur_arg])) {
6260 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006261#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006262 if (!*args[cur_arg + 1]) {
6263 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6264 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006267 }
6268
6269 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006270 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6271 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006272 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006273 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6274 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006275 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6276 char *name, *end;
6277
6278 name = args[cur_arg+1] + 7;
6279 while (isspace(*name))
6280 name++;
6281
6282 end = name;
6283 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6284 end++;
6285
Willy Tarreauef9a3602012-12-08 22:29:20 +01006286 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6287 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6288 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6289 curproxy->conn_src.bind_hdr_len = end - name;
6290 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6291 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6292 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006293
6294 /* now look for an occurrence number */
6295 while (isspace(*end))
6296 end++;
6297 if (*end == ',') {
6298 end++;
6299 name = end;
6300 if (*end == '-')
6301 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006302 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006303 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006304 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006305 }
6306
Willy Tarreauef9a3602012-12-08 22:29:20 +01006307 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006308 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6309 " occurrences values smaller than %d.\n",
6310 file, linenum, MAX_HDR_HISTORY);
6311 err_code |= ERR_ALERT | ERR_FATAL;
6312 goto out;
6313 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006314 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006315 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006316
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006317 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006318 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006319 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006320 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006321 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006322 goto out;
6323 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006324
6325 proto = protocol_by_family(sk->ss_family);
6326 if (!proto || !proto->connect) {
6327 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6328 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006329 err_code |= ERR_ALERT | ERR_FATAL;
6330 goto out;
6331 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006332
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006333 if (port1 != port2) {
6334 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6335 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006336 err_code |= ERR_ALERT | ERR_FATAL;
6337 goto out;
6338 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006339 curproxy->conn_src.tproxy_addr = *sk;
6340 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006341 }
6342 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006343#else /* no TPROXY support */
6344 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006345 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006346 err_code |= ERR_ALERT | ERR_FATAL;
6347 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006348#endif
6349 cur_arg += 2;
6350 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006351 }
6352
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006353 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6354#ifdef SO_BINDTODEVICE
6355 if (!*args[cur_arg + 1]) {
6356 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6357 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006358 err_code |= ERR_ALERT | ERR_FATAL;
6359 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006360 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006361 free(curproxy->conn_src.iface_name);
6362 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6363 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006364 global.last_checks |= LSTCHK_NETADM;
6365#else
6366 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6367 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006368 err_code |= ERR_ALERT | ERR_FATAL;
6369 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006370#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006371 cur_arg += 2;
6372 continue;
6373 }
6374 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006375 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006376 err_code |= ERR_ALERT | ERR_FATAL;
6377 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006380 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6381 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6382 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006383 err_code |= ERR_ALERT | ERR_FATAL;
6384 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006387 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6389 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006390 err_code |= ERR_ALERT | ERR_FATAL;
6391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393
6394 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006395 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006396 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006397 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 }
6400 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006401 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006402 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006403 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006404 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 }
6407 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006408 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006409 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006410 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006411 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
6414 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006415 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006416 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006417 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006418 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
6421 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006423 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006424 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006428 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006430 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006433 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6438 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006439 err_code |= ERR_ALERT | ERR_FATAL;
6440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006442
6443 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006444 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006445 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006446 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
6449 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006451 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006452 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006453 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
6456 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006458 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006459 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006460 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006465 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006466 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006472 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006473 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006477 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006479 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006480 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006481 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006482 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006485 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006486
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 if (curproxy == &defproxy) {
6488 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006489 err_code |= ERR_ALERT | ERR_FATAL;
6490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006492 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006493 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 if (*(args[1]) == 0) {
6496 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006497 err_code |= ERR_ALERT | ERR_FATAL;
6498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006500
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006501 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006502 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6503 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6504 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006505 err_code |= ERR_ALERT | ERR_FATAL;
6506 goto out;
6507 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006508 err_code |= warnif_cond_conflicts(cond,
6509 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6510 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006511 }
6512 else if (*args[2]) {
6513 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6514 file, linenum, args[0], args[2]);
6515 err_code |= ERR_ALERT | ERR_FATAL;
6516 goto out;
6517 }
6518
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006519 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006520 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006521 wl->s = strdup(args[1]);
6522 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006523 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524 }
6525 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006526 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6528 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006529 err_code |= ERR_ALERT | ERR_FATAL;
6530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006531 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006532
Willy Tarreauade5ec42010-01-28 19:33:49 +01006533 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006534 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006535 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006536 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 }
6539 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006540 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006541 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006542 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006543 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 }
6546 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006547 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006548 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006549 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006550 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 }
6553 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006554 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006557 err_code |= ERR_ALERT | ERR_FATAL;
6558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559 }
6560
Willy Tarreauade5ec42010-01-28 19:33:49 +01006561 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006562 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006563 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006564 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006566 }
6567 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006568 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006569 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006570 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006571 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006573 }
6574 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006575 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006576 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006577 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006578 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580 }
6581 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006582 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006583
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 if (curproxy == &defproxy) {
6585 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006586 err_code |= ERR_ALERT | ERR_FATAL;
6587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006589 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006590 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 if (*(args[1]) == 0) {
6593 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006594 err_code |= ERR_ALERT | ERR_FATAL;
6595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006596 }
6597
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006598 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006599 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6600 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6601 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006602 err_code |= ERR_ALERT | ERR_FATAL;
6603 goto out;
6604 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006605 err_code |= warnif_cond_conflicts(cond,
6606 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6607 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006608 }
6609 else if (*args[2]) {
6610 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6611 file, linenum, args[0], args[2]);
6612 err_code |= ERR_ALERT | ERR_FATAL;
6613 goto out;
6614 }
6615
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006616 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006617 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006618 wl->s = strdup(args[1]);
6619 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006620 }
6621 else if (!strcmp(args[0], "errorloc") ||
6622 !strcmp(args[0], "errorloc302") ||
6623 !strcmp(args[0], "errorloc303")) { /* error location */
6624 int errnum, errlen;
6625 char *err;
6626
Willy Tarreau977b8e42006-12-29 14:19:17 +01006627 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006629
Willy Tarreaubaaee002006-06-26 02:48:02 +02006630 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006631 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006632 err_code |= ERR_ALERT | ERR_FATAL;
6633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006634 }
6635
6636 errnum = atol(args[1]);
6637 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006638 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6639 err = malloc(errlen);
6640 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006641 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006642 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6643 err = malloc(errlen);
6644 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006645 }
6646
Willy Tarreau0f772532006-12-23 20:51:41 +01006647 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6648 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006649 chunk_destroy(&curproxy->errmsg[rc]);
6650 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006651 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006653 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006654
6655 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006656 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6657 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006658 free(err);
6659 }
6660 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006661 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6662 int errnum, errlen, fd;
6663 char *err;
6664 struct stat stat;
6665
6666 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006667 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006668
6669 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006670 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006671 err_code |= ERR_ALERT | ERR_FATAL;
6672 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006673 }
6674
6675 fd = open(args[2], O_RDONLY);
6676 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6677 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6678 file, linenum, args[2], args[1]);
6679 if (fd >= 0)
6680 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006681 err_code |= ERR_ALERT | ERR_FATAL;
6682 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006683 }
6684
Willy Tarreau27a674e2009-08-17 07:23:33 +02006685 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006686 errlen = stat.st_size;
6687 } else {
6688 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006689 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006690 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006691 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006692 }
6693
6694 err = malloc(errlen); /* malloc() must succeed during parsing */
6695 errnum = read(fd, err, errlen);
6696 if (errnum != errlen) {
6697 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6698 file, linenum, args[2], args[1]);
6699 close(fd);
6700 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006701 err_code |= ERR_ALERT | ERR_FATAL;
6702 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006703 }
6704 close(fd);
6705
6706 errnum = atol(args[1]);
6707 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6708 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006709 chunk_destroy(&curproxy->errmsg[rc]);
6710 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006711 break;
6712 }
6713 }
6714
6715 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006716 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6717 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006718 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006719 free(err);
6720 }
6721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006722 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006723 struct cfg_kw_list *kwl;
6724 int index;
6725
6726 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6727 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6728 if (kwl->kw[index].section != CFG_LISTEN)
6729 continue;
6730 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6731 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006732 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006733 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006734 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006735 err_code |= ERR_ALERT | ERR_FATAL;
6736 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006737 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006738 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006739 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006740 err_code |= ERR_WARN;
6741 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006742 }
Willy Tarreau93893792009-07-23 13:19:11 +02006743 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006744 }
6745 }
6746 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006747
Willy Tarreau6daf3432008-01-22 16:44:08 +01006748 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006749 err_code |= ERR_ALERT | ERR_FATAL;
6750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006751 }
Willy Tarreau93893792009-07-23 13:19:11 +02006752 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006753 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006754 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006755}
6756
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006757int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006758cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6759{
6760#ifdef CONFIG_HAP_NS
6761 const char *err;
6762 const char *item = args[0];
6763
6764 if (!strcmp(item, "namespace_list")) {
6765 return 0;
6766 }
6767 else if (!strcmp(item, "namespace")) {
6768 size_t idx = 1;
6769 const char *current;
6770 while (*(current = args[idx++])) {
6771 err = invalid_char(current);
6772 if (err) {
6773 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6774 file, linenum, *err, item, current);
6775 return ERR_ALERT | ERR_FATAL;
6776 }
6777
6778 if (netns_store_lookup(current, strlen(current))) {
6779 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6780 file, linenum, current);
6781 return ERR_ALERT | ERR_FATAL;
6782 }
6783 if (!netns_store_insert(current)) {
6784 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6785 file, linenum, current);
6786 return ERR_ALERT | ERR_FATAL;
6787 }
6788 }
6789 }
6790
6791 return 0;
6792#else
6793 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6794 file, linenum);
6795 return ERR_ALERT | ERR_FATAL;
6796#endif
6797}
6798
6799int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6801{
6802
6803 int err_code = 0;
6804 const char *err;
6805
6806 if (!strcmp(args[0], "userlist")) { /* new userlist */
6807 struct userlist *newul;
6808
6809 if (!*args[1]) {
6810 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6811 file, linenum, args[0]);
6812 err_code |= ERR_ALERT | ERR_FATAL;
6813 goto out;
6814 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006815 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6816 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006817
6818 err = invalid_char(args[1]);
6819 if (err) {
6820 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6821 file, linenum, *err, args[0], args[1]);
6822 err_code |= ERR_ALERT | ERR_FATAL;
6823 goto out;
6824 }
6825
6826 for (newul = userlist; newul; newul = newul->next)
6827 if (!strcmp(newul->name, args[1])) {
6828 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6829 file, linenum, args[1]);
6830 err_code |= ERR_WARN;
6831 goto out;
6832 }
6833
Vincent Bernat02779b62016-04-03 13:48:43 +02006834 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006835 if (!newul) {
6836 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6837 err_code |= ERR_ALERT | ERR_ABORT;
6838 goto out;
6839 }
6840
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006841 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006842 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006843 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6844 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006845 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006846 goto out;
6847 }
6848
6849 newul->next = userlist;
6850 userlist = newul;
6851
6852 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006853 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006854 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006855 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006856
6857 if (!*args[1]) {
6858 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6859 file, linenum, args[0]);
6860 err_code |= ERR_ALERT | ERR_FATAL;
6861 goto out;
6862 }
6863
6864 err = invalid_char(args[1]);
6865 if (err) {
6866 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6867 file, linenum, *err, args[0], args[1]);
6868 err_code |= ERR_ALERT | ERR_FATAL;
6869 goto out;
6870 }
6871
William Lallemand4ac9f542015-05-28 18:03:51 +02006872 if (!userlist)
6873 goto out;
6874
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006875 for (ag = userlist->groups; ag; ag = ag->next)
6876 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006877 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6878 file, linenum, args[1], userlist->name);
6879 err_code |= ERR_ALERT;
6880 goto out;
6881 }
6882
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006883 ag = calloc(1, sizeof(*ag));
6884 if (!ag) {
6885 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6886 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006887 goto out;
6888 }
6889
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006890 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006891 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006892 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6893 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006894 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006895 goto out;
6896 }
6897
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006898 cur_arg = 2;
6899
6900 while (*args[cur_arg]) {
6901 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006902 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006903 cur_arg += 2;
6904 continue;
6905 } else {
6906 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6907 file, linenum, args[0]);
6908 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006909 free(ag->groupusers);
6910 free(ag->name);
6911 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006912 goto out;
6913 }
6914 }
6915
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006916 ag->next = userlist->groups;
6917 userlist->groups = ag;
6918
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006919 } else if (!strcmp(args[0], "user")) { /* new user */
6920 struct auth_users *newuser;
6921 int cur_arg;
6922
6923 if (!*args[1]) {
6924 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6925 file, linenum, args[0]);
6926 err_code |= ERR_ALERT | ERR_FATAL;
6927 goto out;
6928 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006929 if (!userlist)
6930 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006931
6932 for (newuser = userlist->users; newuser; newuser = newuser->next)
6933 if (!strcmp(newuser->user, args[1])) {
6934 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6935 file, linenum, args[1], userlist->name);
6936 err_code |= ERR_ALERT;
6937 goto out;
6938 }
6939
Vincent Bernat02779b62016-04-03 13:48:43 +02006940 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006941 if (!newuser) {
6942 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6943 err_code |= ERR_ALERT | ERR_ABORT;
6944 goto out;
6945 }
6946
6947 newuser->user = strdup(args[1]);
6948
6949 newuser->next = userlist->users;
6950 userlist->users = newuser;
6951
6952 cur_arg = 2;
6953
6954 while (*args[cur_arg]) {
6955 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006956#ifdef CONFIG_HAP_CRYPT
6957 if (!crypt("", args[cur_arg + 1])) {
6958 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6959 file, linenum, newuser->user);
6960 err_code |= ERR_ALERT | ERR_FATAL;
6961 goto out;
6962 }
6963#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006964 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6965 file, linenum);
6966 err_code |= ERR_ALERT;
6967#endif
6968 newuser->pass = strdup(args[cur_arg + 1]);
6969 cur_arg += 2;
6970 continue;
6971 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6972 newuser->pass = strdup(args[cur_arg + 1]);
6973 newuser->flags |= AU_O_INSECURE;
6974 cur_arg += 2;
6975 continue;
6976 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006977 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006978 cur_arg += 2;
6979 continue;
6980 } else {
6981 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6982 file, linenum, args[0]);
6983 err_code |= ERR_ALERT | ERR_FATAL;
6984 goto out;
6985 }
6986 }
6987 } else {
6988 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6989 err_code |= ERR_ALERT | ERR_FATAL;
6990 }
6991
6992out:
6993 return err_code;
6994}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995
6996/*
6997 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006998 * Returns the error code, 0 if OK, or any combination of :
6999 * - ERR_ABORT: must abort ASAP
7000 * - ERR_FATAL: we can continue parsing but not start the service
7001 * - ERR_WARN: a warning has been emitted
7002 * - ERR_ALERT: an alert has been emitted
7003 * Only the two first ones can stop processing, the two others are just
7004 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007006int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007007{
William Lallemand64e84512015-05-12 14:25:37 +02007008 char *thisline;
7009 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010 FILE *f;
7011 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007012 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007013 struct cfg_section *cs = NULL;
7014 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007015 int readbytes = 0;
7016
7017 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007018 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007019 return -1;
7020 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007021
David Carlier97880bb2016-04-08 10:35:26 +01007022 if ((f=fopen(file,"r")) == NULL) {
7023 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007026
William Lallemandb2f07452015-05-12 14:27:13 +02007027next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007028 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007029 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007030 char *end;
7031 char *args[MAX_LINE_ARGS + 1];
7032 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007033 int dquote = 0; /* double quote */
7034 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007035
Willy Tarreaubaaee002006-06-26 02:48:02 +02007036 linenum++;
7037
7038 end = line + strlen(line);
7039
William Lallemand64e84512015-05-12 14:25:37 +02007040 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007041 /* Check if we reached the limit and the last char is not \n.
7042 * Watch out for the last line without the terminating '\n'!
7043 */
William Lallemand64e84512015-05-12 14:25:37 +02007044 char *newline;
7045 int newlinesize = linesize * 2;
7046
7047 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7048 if (newline == NULL) {
7049 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7050 file, linenum);
7051 err_code |= ERR_ALERT | ERR_FATAL;
7052 continue;
7053 }
7054
7055 readbytes = linesize - 1;
7056 linesize = newlinesize;
7057 thisline = newline;
7058 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007059 }
7060
William Lallemand64e84512015-05-12 14:25:37 +02007061 readbytes = 0;
7062
Willy Tarreaubaaee002006-06-26 02:48:02 +02007063 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007064 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007065 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007066
Willy Tarreaubaaee002006-06-26 02:48:02 +02007067 arg = 0;
7068 args[arg] = line;
7069
7070 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007071 if (*line == '"' && !squote) { /* double quote outside single quotes */
7072 if (dquote)
7073 dquote = 0;
7074 else
7075 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007076 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007077 end--;
7078 }
7079 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7080 if (squote)
7081 squote = 0;
7082 else
7083 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007084 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007085 end--;
7086 }
7087 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7089 * C equivalent value. Other combinations left unchanged (eg: \1).
7090 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007091 int skip = 0;
7092 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7093 *line = line[1];
7094 skip = 1;
7095 }
7096 else if (line[1] == 'r') {
7097 *line = '\r';
7098 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007100 else if (line[1] == 'n') {
7101 *line = '\n';
7102 skip = 1;
7103 }
7104 else if (line[1] == 't') {
7105 *line = '\t';
7106 skip = 1;
7107 }
7108 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007109 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007110 unsigned char hex1, hex2;
7111 hex1 = toupper(line[2]) - '0';
7112 hex2 = toupper(line[3]) - '0';
7113 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7114 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7115 *line = (hex1<<4) + hex2;
7116 skip = 3;
7117 }
7118 else {
7119 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007120 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007121 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007122 } else if (line[1] == '"') {
7123 *line = '"';
7124 skip = 1;
7125 } else if (line[1] == '\'') {
7126 *line = '\'';
7127 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007128 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7129 *line = '$';
7130 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007131 }
7132 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007133 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007134 end -= skip;
7135 }
7136 line++;
7137 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007138 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007139 /* end of string, end of loop */
7140 *line = 0;
7141 break;
7142 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007143 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007144 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007145 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007146 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007147 line++;
7148 args[++arg] = line;
7149 }
William Lallemandb2f07452015-05-12 14:27:13 +02007150 else if (dquote && *line == '$') {
7151 /* environment variables are evaluated inside double quotes */
7152 char *var_beg;
7153 char *var_end;
7154 char save_char;
7155 char *value;
7156 int val_len;
7157 int newlinesize;
7158 int braces = 0;
7159
7160 var_beg = line + 1;
7161 var_end = var_beg;
7162
7163 if (*var_beg == '{') {
7164 var_beg++;
7165 var_end++;
7166 braces = 1;
7167 }
7168
7169 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7170 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7171 err_code |= ERR_ALERT | ERR_FATAL;
7172 goto next_line; /* skip current line */
7173 }
7174
7175 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7176 var_end++;
7177
7178 save_char = *var_end;
7179 *var_end = '\0';
7180 value = getenv(var_beg);
7181 *var_end = save_char;
7182 val_len = value ? strlen(value) : 0;
7183
7184 if (braces) {
7185 if (*var_end == '}') {
7186 var_end++;
7187 braces = 0;
7188 } else {
7189 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7190 err_code |= ERR_ALERT | ERR_FATAL;
7191 goto next_line; /* skip current line */
7192 }
7193 }
7194
7195 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7196
7197 /* if not enough space in thisline */
7198 if (newlinesize > linesize) {
7199 char *newline;
7200
7201 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7202 if (newline == NULL) {
7203 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7204 err_code |= ERR_ALERT | ERR_FATAL;
7205 goto next_line; /* slip current line */
7206 }
7207 /* recompute pointers if realloc returns a new pointer */
7208 if (newline != thisline) {
7209 int i;
7210 int diff;
7211
7212 for (i = 0; i <= arg; i++) {
7213 diff = args[i] - thisline;
7214 args[i] = newline + diff;
7215 }
7216
7217 diff = var_end - thisline;
7218 var_end = newline + diff;
7219 diff = end - thisline;
7220 end = newline + diff;
7221 diff = line - thisline;
7222 line = newline + diff;
7223 thisline = newline;
7224 }
7225 linesize = newlinesize;
7226 }
7227
7228 /* insert value inside the line */
7229 memmove(line + val_len, var_end, end - var_end + 1);
7230 memcpy(line, value, val_len);
7231 end += val_len - (var_end - line);
7232 line += val_len;
7233 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007234 else {
7235 line++;
7236 }
7237 }
William Lallemandb2f07452015-05-12 14:27:13 +02007238
William Lallemandf9873ba2015-05-05 17:37:14 +02007239 if (dquote) {
7240 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7241 err_code |= ERR_ALERT | ERR_FATAL;
7242 }
7243
7244 if (squote) {
7245 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7246 err_code |= ERR_ALERT | ERR_FATAL;
7247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007248
7249 /* empty line */
7250 if (!**args)
7251 continue;
7252
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007253 if (*line) {
7254 /* we had to stop due to too many args.
7255 * Let's terminate the string, print the offending part then cut the
7256 * last arg.
7257 */
7258 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7259 line++;
7260 *line = '\0';
7261
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007262 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007263 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007264 err_code |= ERR_ALERT | ERR_FATAL;
7265 args[arg] = line;
7266 }
7267
Willy Tarreau540abe42007-05-02 20:50:16 +02007268 /* zero out remaining args and ensure that at least one entry
7269 * is zeroed out.
7270 */
7271 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007272 args[arg] = line;
7273 }
7274
Willy Tarreau3842f002009-06-14 11:39:52 +02007275 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007276 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007277 char *tmp;
7278
Willy Tarreau3842f002009-06-14 11:39:52 +02007279 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007280 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007281 for (arg=0; *args[arg+1]; arg++)
7282 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007283 *tmp = '\0'; // fix the next arg to \0
7284 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007285 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007286 else if (!strcmp(args[0], "default")) {
7287 kwm = KWM_DEF;
7288 for (arg=0; *args[arg+1]; arg++)
7289 args[arg] = args[arg+1]; // shift args after inversion
7290 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007291
William Lallemand0f99e342011-10-12 17:50:54 +02007292 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7293 strcmp(args[0], "log") != 0) {
7294 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007295 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007296 }
7297
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007298 /* detect section start */
7299 list_for_each_entry(ics, &sections, list) {
7300 if (strcmp(args[0], ics->section_name) == 0) {
7301 cursection = ics->section_name;
7302 cs = ics;
7303 break;
7304 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007305 }
7306
Willy Tarreaubaaee002006-06-26 02:48:02 +02007307 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007308 if (cs)
7309 err_code |= cs->section_parser(file, linenum, args, kwm);
7310 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007311 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007312 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007313 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007314
7315 if (err_code & ERR_ABORT)
7316 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007317 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007318 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007319 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007320 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007321 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007322}
7323
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324/* This function propagates processes from frontend <from> to backend <to> so
7325 * that it is always guaranteed that a backend pointed to by a frontend is
7326 * bound to all of its processes. After that, if the target is a "listen"
7327 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007328 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007329 * checked first to ensure that <to> is already bound to all processes of
7330 * <from>, there is no risk of looping and we ensure to follow the shortest
7331 * path to the destination.
7332 *
7333 * It is possible to set <to> to NULL for the first call so that the function
7334 * takes care of visiting the initial frontend in <from>.
7335 *
7336 * It is important to note that the function relies on the fact that all names
7337 * have already been resolved.
7338 */
7339void propagate_processes(struct proxy *from, struct proxy *to)
7340{
7341 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007342
7343 if (to) {
7344 /* check whether we need to go down */
7345 if (from->bind_proc &&
7346 (from->bind_proc & to->bind_proc) == from->bind_proc)
7347 return;
7348
7349 if (!from->bind_proc && !to->bind_proc)
7350 return;
7351
7352 to->bind_proc = from->bind_proc ?
7353 (to->bind_proc | from->bind_proc) : 0;
7354
7355 /* now propagate down */
7356 from = to;
7357 }
7358
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007359 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007360 return;
7361
Willy Tarreauf6b70012014-12-18 14:00:43 +01007362 if (from->state == PR_STSTOPPED)
7363 return;
7364
Willy Tarreau64ab6072014-09-16 12:17:36 +02007365 /* default_backend */
7366 if (from->defbe.be)
7367 propagate_processes(from, from->defbe.be);
7368
7369 /* use_backend */
7370 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007371 if (rule->dynamic)
7372 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007373 to = rule->be.backend;
7374 propagate_processes(from, to);
7375 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007376}
7377
Willy Tarreaubb925012009-07-23 13:36:36 +02007378/*
7379 * Returns the error code, 0 if OK, or any combination of :
7380 * - ERR_ABORT: must abort ASAP
7381 * - ERR_FATAL: we can continue parsing but not start the service
7382 * - ERR_WARN: a warning has been emitted
7383 * - ERR_ALERT: an alert has been emitted
7384 * Only the two first ones can stop processing, the two others are just
7385 * indicators.
7386 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007387int check_config_validity()
7388{
7389 int cfgerr = 0;
7390 struct proxy *curproxy = NULL;
7391 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007392 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007393 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007394 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007395
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007396 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007397 /*
7398 * Now, check for the integrity of all that we have collected.
7399 */
7400
7401 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007402 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007403
Willy Tarreau193b8c62012-11-22 00:17:38 +01007404 if (!global.tune.max_http_hdr)
7405 global.tune.max_http_hdr = MAX_HTTP_HDR;
7406
7407 if (!global.tune.cookie_len)
7408 global.tune.cookie_len = CAPTURE_LEN;
7409
7410 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7411
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007412 /* Post initialisation of the users and groups lists. */
7413 err_code = userlist_postinit();
7414 if (err_code != ERR_NONE)
7415 goto out;
7416
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007417 /* first, we will invert the proxy list order */
7418 curproxy = NULL;
7419 while (proxy) {
7420 struct proxy *next;
7421
7422 next = proxy->next;
7423 proxy->next = curproxy;
7424 curproxy = proxy;
7425 if (!next)
7426 break;
7427 proxy = next;
7428 }
7429
Willy Tarreau419ead82014-09-16 13:41:21 +02007430 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007431 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007432 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007433 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007434 struct act_rule *trule;
7435 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007436 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007437 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007438 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007439
Willy Tarreau050536d2012-10-04 08:47:34 +02007440 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007441 /* proxy ID not set, use automatic numbering with first
7442 * spare entry starting with next_pxid.
7443 */
7444 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7445 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7446 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007447 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007448 next_pxid++;
7449
Willy Tarreau55ea7572007-06-17 19:56:27 +02007450
Willy Tarreaubaaee002006-06-26 02:48:02 +02007451 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007452 /* ensure we don't keep listeners uselessly bound */
7453 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007454 free((void *)curproxy->table.peers.name);
7455 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007456 continue;
7457 }
7458
Willy Tarreau102df612014-05-07 23:56:38 +02007459 /* Check multi-process mode compatibility for the current proxy */
7460
7461 if (curproxy->bind_proc) {
7462 /* an explicit bind-process was specified, let's check how many
7463 * processes remain.
7464 */
David Carliere6c39412015-07-02 07:00:17 +00007465 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007466
7467 curproxy->bind_proc &= nbits(global.nbproc);
7468 if (!curproxy->bind_proc && nbproc == 1) {
7469 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);
7470 curproxy->bind_proc = 1;
7471 }
7472 else if (!curproxy->bind_proc && nbproc > 1) {
7473 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);
7474 curproxy->bind_proc = 0;
7475 }
7476 }
7477
Willy Tarreau3d209582014-05-09 17:06:11 +02007478 /* check and reduce the bind-proc of each listener */
7479 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7480 unsigned long mask;
7481
7482 if (!bind_conf->bind_proc)
7483 continue;
7484
7485 mask = nbits(global.nbproc);
7486 if (curproxy->bind_proc)
7487 mask &= curproxy->bind_proc;
7488 /* mask cannot be null here thanks to the previous checks */
7489
David Carliere6c39412015-07-02 07:00:17 +00007490 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007491 bind_conf->bind_proc &= mask;
7492
7493 if (!bind_conf->bind_proc && nbproc == 1) {
7494 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",
7495 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7496 bind_conf->bind_proc = mask & ~(mask - 1);
7497 }
7498 else if (!bind_conf->bind_proc && nbproc > 1) {
7499 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",
7500 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7501 bind_conf->bind_proc = 0;
7502 }
7503 }
7504
Willy Tarreauff01a212009-03-15 13:46:16 +01007505 switch (curproxy->mode) {
7506 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007507 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007508 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007509 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7510 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007511 cfgerr++;
7512 }
7513
7514 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007515 Warning("config : servers will be ignored for %s '%s'.\n",
7516 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007517 break;
7518
7519 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007520 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007521 break;
7522
7523 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007524 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007525 break;
7526 }
7527
Willy Tarreauf3934b82015-08-11 11:36:45 +02007528 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7529 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7530 proxy_type_str(curproxy), curproxy->id);
7531 err_code |= ERR_WARN;
7532 }
7533
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007534 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007535 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007536 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007537 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7538 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007539 cfgerr++;
7540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007541#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007542 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007543 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7544 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007545 cfgerr++;
7546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007547#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007548 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007549 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7550 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007551 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007552 }
7553 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007554 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007555 /* If no LB algo is set in a backend, and we're not in
7556 * transparent mode, dispatch mode nor proxy mode, we
7557 * want to use balance roundrobin by default.
7558 */
7559 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7560 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007561 }
7562 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007563
Willy Tarreau1620ec32011-08-06 17:05:02 +02007564 if (curproxy->options & PR_O_DISPATCH)
7565 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7566 else if (curproxy->options & PR_O_HTTP_PROXY)
7567 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7568 else if (curproxy->options & PR_O_TRANSP)
7569 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007570
Willy Tarreau1620ec32011-08-06 17:05:02 +02007571 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7572 if (curproxy->options & PR_O_DISABLE404) {
7573 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7574 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7575 err_code |= ERR_WARN;
7576 curproxy->options &= ~PR_O_DISABLE404;
7577 }
7578 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7579 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7580 "send-state", proxy_type_str(curproxy), curproxy->id);
7581 err_code |= ERR_WARN;
7582 curproxy->options &= ~PR_O2_CHK_SNDST;
7583 }
Willy Tarreauef781042010-01-27 11:53:01 +01007584 }
7585
Simon Horman98637e52014-06-20 12:30:16 +09007586 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7587 if (!global.external_check) {
7588 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7589 curproxy->id, "option external-check");
7590 cfgerr++;
7591 }
7592 if (!curproxy->check_command) {
7593 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7594 curproxy->id, "option external-check");
7595 cfgerr++;
7596 }
7597 }
7598
Simon Horman64e34162015-02-06 11:11:57 +09007599 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007600 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7601 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007602 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7603 "'email-alert myhostname', or 'email-alert to' "
7604 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007605 "to be present).\n",
7606 proxy_type_str(curproxy), curproxy->id);
7607 err_code |= ERR_WARN;
7608 free_email_alert(curproxy);
7609 }
7610 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007611 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007612 }
7613
Simon Horman98637e52014-06-20 12:30:16 +09007614 if (curproxy->check_command) {
7615 int clear = 0;
7616 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7617 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7618 "external-check command", proxy_type_str(curproxy), curproxy->id);
7619 err_code |= ERR_WARN;
7620 clear = 1;
7621 }
7622 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007623 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007624 curproxy->id, "external-check command");
7625 cfgerr++;
7626 }
7627 if (clear) {
7628 free(curproxy->check_command);
7629 curproxy->check_command = NULL;
7630 }
7631 }
7632
7633 if (curproxy->check_path) {
7634 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7635 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7636 "external-check path", proxy_type_str(curproxy), curproxy->id);
7637 err_code |= ERR_WARN;
7638 free(curproxy->check_path);
7639 curproxy->check_path = NULL;
7640 }
7641 }
7642
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007643 /* if a default backend was specified, let's find it */
7644 if (curproxy->defbe.name) {
7645 struct proxy *target;
7646
Willy Tarreauafb39922015-05-26 12:04:09 +02007647 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007648 if (!target) {
7649 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7650 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007651 cfgerr++;
7652 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007653 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7654 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007655 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007656 } else if (target->mode != curproxy->mode &&
7657 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7658
7659 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7660 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7661 curproxy->conf.file, curproxy->conf.line,
7662 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7663 target->conf.file, target->conf.line);
7664 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007665 } else {
7666 free(curproxy->defbe.name);
7667 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007668
7669 /* Emit a warning if this proxy also has some servers */
7670 if (curproxy->srv) {
7671 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7672 curproxy->id);
7673 err_code |= ERR_WARN;
7674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007675 }
7676 }
7677
Willy Tarreau55ea7572007-06-17 19:56:27 +02007678 /* find the target proxy for 'use_backend' rules */
7679 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007680 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007681 struct logformat_node *node;
7682 char *pxname;
7683
7684 /* Try to parse the string as a log format expression. If the result
7685 * of the parsing is only one entry containing a simple string, then
7686 * it's a standard string corresponding to a static rule, thus the
7687 * parsing is cancelled and be.name is restored to be resolved.
7688 */
7689 pxname = rule->be.name;
7690 LIST_INIT(&rule->be.expr);
7691 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7692 curproxy->conf.args.file, curproxy->conf.args.line);
7693 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7694
7695 if (!LIST_ISEMPTY(&rule->be.expr)) {
7696 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7697 rule->dynamic = 1;
7698 free(pxname);
7699 continue;
7700 }
7701 /* simple string: free the expression and fall back to static rule */
7702 free(node->arg);
7703 free(node);
7704 }
7705
7706 rule->dynamic = 0;
7707 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007708
Willy Tarreauafb39922015-05-26 12:04:09 +02007709 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007710 if (!target) {
7711 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7712 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007713 cfgerr++;
7714 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007715 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7716 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007717 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007718 } else if (target->mode != curproxy->mode &&
7719 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7720
7721 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7722 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7723 curproxy->conf.file, curproxy->conf.line,
7724 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7725 target->conf.file, target->conf.line);
7726 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007727 } else {
7728 free((void *)rule->be.name);
7729 rule->be.backend = target;
7730 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007731 }
7732
Willy Tarreau64ab6072014-09-16 12:17:36 +02007733 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007734 list_for_each_entry(srule, &curproxy->server_rules, list) {
7735 struct server *target = findserver(curproxy, srule->srv.name);
7736
7737 if (!target) {
7738 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7739 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7740 cfgerr++;
7741 continue;
7742 }
7743 free((void *)srule->srv.name);
7744 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007745 }
7746
Emeric Brunb982a3d2010-01-04 15:45:53 +01007747 /* find the target table for 'stick' rules */
7748 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7749 struct proxy *target;
7750
Emeric Brun1d33b292010-01-04 15:47:17 +01007751 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7752 if (mrule->flags & STK_IS_STORE)
7753 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7754
Emeric Brunb982a3d2010-01-04 15:45:53 +01007755 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007756 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007757 else
7758 target = curproxy;
7759
7760 if (!target) {
7761 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7762 curproxy->id, mrule->table.name);
7763 cfgerr++;
7764 }
7765 else if (target->table.size == 0) {
7766 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7767 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7768 cfgerr++;
7769 }
Willy Tarreau12785782012-04-27 21:37:17 +02007770 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7771 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007772 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7773 cfgerr++;
7774 }
7775 else {
7776 free((void *)mrule->table.name);
7777 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007778 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007779 }
7780 }
7781
7782 /* find the target table for 'store response' rules */
7783 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7784 struct proxy *target;
7785
Emeric Brun1d33b292010-01-04 15:47:17 +01007786 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7787
Emeric Brunb982a3d2010-01-04 15:45:53 +01007788 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007789 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007790 else
7791 target = curproxy;
7792
7793 if (!target) {
7794 Alert("Proxy '%s': unable to find store table '%s'.\n",
7795 curproxy->id, mrule->table.name);
7796 cfgerr++;
7797 }
7798 else if (target->table.size == 0) {
7799 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7800 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7801 cfgerr++;
7802 }
Willy Tarreau12785782012-04-27 21:37:17 +02007803 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7804 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007805 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7806 cfgerr++;
7807 }
7808 else {
7809 free((void *)mrule->table.name);
7810 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007811 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007812 }
7813 }
7814
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007815 /* find the target table for 'tcp-request' layer 4 rules */
7816 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7817 struct proxy *target;
7818
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007819 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007820 continue;
7821
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007822 if (trule->arg.trk_ctr.table.n)
7823 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007824 else
7825 target = curproxy;
7826
7827 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007828 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007829 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007830 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007831 cfgerr++;
7832 }
7833 else if (target->table.size == 0) {
7834 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007835 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007836 cfgerr++;
7837 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007838 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007839 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007840 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007841 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007842 cfgerr++;
7843 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007844 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007845 free(trule->arg.trk_ctr.table.n);
7846 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007847 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007848 * to pass a list of counters to track and allocate them right here using
7849 * stktable_alloc_data_type().
7850 */
7851 }
7852 }
7853
Willy Tarreau620408f2016-10-21 16:37:51 +02007854 /* find the target table for 'tcp-request' layer 5 rules */
7855 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7856 struct proxy *target;
7857
7858 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7859 continue;
7860
7861 if (trule->arg.trk_ctr.table.n)
7862 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7863 else
7864 target = curproxy;
7865
7866 if (!target) {
7867 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7868 curproxy->id, trule->arg.trk_ctr.table.n,
7869 tcp_trk_idx(trule->action));
7870 cfgerr++;
7871 }
7872 else if (target->table.size == 0) {
7873 Alert("Proxy '%s': table '%s' used but not configured.\n",
7874 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7875 cfgerr++;
7876 }
7877 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7878 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7879 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7880 tcp_trk_idx(trule->action));
7881 cfgerr++;
7882 }
7883 else {
7884 free(trule->arg.trk_ctr.table.n);
7885 trule->arg.trk_ctr.table.t = &target->table;
7886 /* Note: if we decide to enhance the track-sc syntax, we may be able
7887 * to pass a list of counters to track and allocate them right here using
7888 * stktable_alloc_data_type().
7889 */
7890 }
7891 }
7892
Willy Tarreaud1f96522010-08-03 19:34:32 +02007893 /* find the target table for 'tcp-request' layer 6 rules */
7894 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7895 struct proxy *target;
7896
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007897 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007898 continue;
7899
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007900 if (trule->arg.trk_ctr.table.n)
7901 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007902 else
7903 target = curproxy;
7904
7905 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007906 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007907 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007908 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007909 cfgerr++;
7910 }
7911 else if (target->table.size == 0) {
7912 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007913 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007914 cfgerr++;
7915 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007916 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007917 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007918 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007919 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007920 cfgerr++;
7921 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007922 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007923 free(trule->arg.trk_ctr.table.n);
7924 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007925 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007926 * to pass a list of counters to track and allocate them right here using
7927 * stktable_alloc_data_type().
7928 */
7929 }
7930 }
7931
Baptiste Assmanne9544932015-11-03 23:31:35 +01007932 /* parse http-request capture rules to ensure id really exists */
7933 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7934 if (hrqrule->action != ACT_CUSTOM ||
7935 hrqrule->action_ptr != http_action_req_capture_by_id)
7936 continue;
7937
7938 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7939 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7940 curproxy->id, hrqrule->arg.capid.idx);
7941 cfgerr++;
7942 }
7943 }
7944
7945 /* parse http-response capture rules to ensure id really exists */
7946 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7947 if (hrqrule->action != ACT_CUSTOM ||
7948 hrqrule->action_ptr != http_action_res_capture_by_id)
7949 continue;
7950
7951 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7952 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7953 curproxy->id, hrqrule->arg.capid.idx);
7954 cfgerr++;
7955 }
7956 }
7957
Willy Tarreau09448f72014-06-25 18:12:15 +02007958 /* find the target table for 'http-request' layer 7 rules */
7959 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7960 struct proxy *target;
7961
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007962 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007963 continue;
7964
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007965 if (hrqrule->arg.trk_ctr.table.n)
7966 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007967 else
7968 target = curproxy;
7969
7970 if (!target) {
7971 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007972 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007973 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007974 cfgerr++;
7975 }
7976 else if (target->table.size == 0) {
7977 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007978 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007979 cfgerr++;
7980 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007981 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007982 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007983 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007984 http_trk_idx(hrqrule->action));
7985 cfgerr++;
7986 }
7987 else {
7988 free(hrqrule->arg.trk_ctr.table.n);
7989 hrqrule->arg.trk_ctr.table.t = &target->table;
7990 /* Note: if we decide to enhance the track-sc syntax, we may be able
7991 * to pass a list of counters to track and allocate them right here using
7992 * stktable_alloc_data_type().
7993 */
7994 }
7995 }
7996
7997 /* find the target table for 'http-response' layer 7 rules */
7998 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7999 struct proxy *target;
8000
8001 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8002 continue;
8003
8004 if (hrqrule->arg.trk_ctr.table.n)
8005 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8006 else
8007 target = curproxy;
8008
8009 if (!target) {
8010 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8011 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8012 http_trk_idx(hrqrule->action));
8013 cfgerr++;
8014 }
8015 else if (target->table.size == 0) {
8016 Alert("Proxy '%s': table '%s' used but not configured.\n",
8017 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8018 cfgerr++;
8019 }
8020 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8021 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8022 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8023 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008024 cfgerr++;
8025 }
8026 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008027 free(hrqrule->arg.trk_ctr.table.n);
8028 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008029 /* Note: if we decide to enhance the track-sc syntax, we may be able
8030 * to pass a list of counters to track and allocate them right here using
8031 * stktable_alloc_data_type().
8032 */
8033 }
8034 }
8035
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008036 /* move any "block" rules at the beginning of the http-request rules */
8037 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8038 /* insert block_rules into http_req_rules at the beginning */
8039 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8040 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8041 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8042 curproxy->http_req_rules.n = curproxy->block_rules.n;
8043 LIST_INIT(&curproxy->block_rules);
8044 }
8045
Emeric Brun32da3c42010-09-23 18:39:19 +02008046 if (curproxy->table.peers.name) {
8047 struct peers *curpeers = peers;
8048
8049 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8050 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8051 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008052 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008053 break;
8054 }
8055 }
8056
8057 if (!curpeers) {
8058 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8059 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008060 free((void *)curproxy->table.peers.name);
8061 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008062 cfgerr++;
8063 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008064 else if (curpeers->state == PR_STSTOPPED) {
8065 /* silently disable this peers section */
8066 curproxy->table.peers.p = NULL;
8067 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008068 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008069 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8070 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008071 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008072 cfgerr++;
8073 }
8074 }
8075
Simon Horman9dc49962015-01-30 11:22:59 +09008076
8077 if (curproxy->email_alert.mailers.name) {
8078 struct mailers *curmailers = mailers;
8079
8080 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8081 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8082 free(curproxy->email_alert.mailers.name);
8083 curproxy->email_alert.mailers.m = curmailers;
8084 curmailers->users++;
8085 break;
8086 }
8087 }
8088
8089 if (!curmailers) {
8090 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8091 curproxy->id, curproxy->email_alert.mailers.name);
8092 free_email_alert(curproxy);
8093 cfgerr++;
8094 }
8095 }
8096
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008097 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008098 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008099 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8100 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8101 "proxy", curproxy->id);
8102 cfgerr++;
8103 goto out_uri_auth_compat;
8104 }
8105
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008106 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008107 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008108 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008109 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008110
Willy Tarreau95fa4692010-02-01 13:05:50 +01008111 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8112 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008113
8114 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008115 uri_auth_compat_req[i++] = "realm";
8116 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8117 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008118
Willy Tarreau95fa4692010-02-01 13:05:50 +01008119 uri_auth_compat_req[i++] = "unless";
8120 uri_auth_compat_req[i++] = "{";
8121 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8122 uri_auth_compat_req[i++] = "}";
8123 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008124
Willy Tarreauff011f22011-01-06 17:51:27 +01008125 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8126 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008127 cfgerr++;
8128 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008129 }
8130
Willy Tarreauff011f22011-01-06 17:51:27 +01008131 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008132
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008133 if (curproxy->uri_auth->auth_realm) {
8134 free(curproxy->uri_auth->auth_realm);
8135 curproxy->uri_auth->auth_realm = NULL;
8136 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008137
8138 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008139 }
8140out_uri_auth_compat:
8141
Dragan Dosen43885c72015-10-01 13:18:13 +02008142 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008143 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008144 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8145 if (!curproxy->conf.logformat_sd_string) {
8146 /* set the default logformat_sd_string */
8147 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8148 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008149 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008150 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008151 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008152
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008153 /* compile the log format */
8154 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008155 if (curproxy->conf.logformat_string != default_http_log_format &&
8156 curproxy->conf.logformat_string != default_tcp_log_format &&
8157 curproxy->conf.logformat_string != clf_http_log_format)
8158 free(curproxy->conf.logformat_string);
8159 curproxy->conf.logformat_string = NULL;
8160 free(curproxy->conf.lfs_file);
8161 curproxy->conf.lfs_file = NULL;
8162 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008163
8164 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8165 free(curproxy->conf.logformat_sd_string);
8166 curproxy->conf.logformat_sd_string = NULL;
8167 free(curproxy->conf.lfsd_file);
8168 curproxy->conf.lfsd_file = NULL;
8169 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008170 }
8171
Willy Tarreau62a61232013-04-12 18:13:46 +02008172 if (curproxy->conf.logformat_string) {
8173 curproxy->conf.args.ctx = ARGC_LOG;
8174 curproxy->conf.args.file = curproxy->conf.lfs_file;
8175 curproxy->conf.args.line = curproxy->conf.lfs_line;
8176 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008177 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008178 curproxy->conf.args.file = NULL;
8179 curproxy->conf.args.line = 0;
8180 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008181
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008182 if (curproxy->conf.logformat_sd_string) {
8183 curproxy->conf.args.ctx = ARGC_LOGSD;
8184 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8185 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8186 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8187 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8188 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8189 curproxy->conf.args.file = NULL;
8190 curproxy->conf.args.line = 0;
8191 }
8192
Willy Tarreau62a61232013-04-12 18:13:46 +02008193 if (curproxy->conf.uniqueid_format_string) {
8194 curproxy->conf.args.ctx = ARGC_UIF;
8195 curproxy->conf.args.file = curproxy->conf.uif_file;
8196 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008197 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008198 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008199 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008200 curproxy->conf.args.file = NULL;
8201 curproxy->conf.args.line = 0;
8202 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008203
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008204 /* only now we can check if some args remain unresolved.
8205 * This must be done after the users and groups resolution.
8206 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008207 cfgerr += smp_resolve_args(curproxy);
8208 if (!cfgerr)
8209 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008210
Willy Tarreau2738a142006-07-08 17:28:09 +02008211 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008212 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008213 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008214 (!curproxy->timeout.connect ||
8215 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008216 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008217 " | While not properly invalid, you will certainly encounter various problems\n"
8218 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008219 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008220 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008221 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008222 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008223
Willy Tarreau1fa31262007-12-03 00:36:16 +01008224 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8225 * We must still support older configurations, so let's find out whether those
8226 * parameters have been set or must be copied from contimeouts.
8227 */
8228 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008229 if (!curproxy->timeout.tarpit ||
8230 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008231 /* tarpit timeout not set. We search in the following order:
8232 * default.tarpit, curr.connect, default.connect.
8233 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008234 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008235 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008236 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008237 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008238 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008239 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008240 }
8241 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008242 (!curproxy->timeout.queue ||
8243 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008244 /* queue timeout not set. We search in the following order:
8245 * default.queue, curr.connect, default.connect.
8246 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008247 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008248 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008249 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008250 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008251 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008252 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008253 }
8254 }
8255
Willy Tarreau1620ec32011-08-06 17:05:02 +02008256 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008257 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008258 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008259 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008260 }
8261
Willy Tarreau215663d2014-06-13 18:30:23 +02008262 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8263 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8264 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8265 proxy_type_str(curproxy), curproxy->id);
8266 err_code |= ERR_WARN;
8267 }
8268
Willy Tarreau193b8c62012-11-22 00:17:38 +01008269 /* ensure that cookie capture length is not too large */
8270 if (curproxy->capture_len >= global.tune.cookie_len) {
8271 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8272 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8273 err_code |= ERR_WARN;
8274 curproxy->capture_len = global.tune.cookie_len - 1;
8275 }
8276
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008277 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008278 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008279 curproxy->req_cap_pool = create_pool("ptrcap",
8280 curproxy->nb_req_cap * sizeof(char *),
8281 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008282 }
8283
8284 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008285 curproxy->rsp_cap_pool = create_pool("ptrcap",
8286 curproxy->nb_rsp_cap * sizeof(char *),
8287 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008288 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008289
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008290 switch (curproxy->load_server_state_from_file) {
8291 case PR_SRV_STATE_FILE_UNSPEC:
8292 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8293 break;
8294 case PR_SRV_STATE_FILE_GLOBAL:
8295 if (!global.server_state_file) {
8296 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",
8297 curproxy->id);
8298 err_code |= ERR_WARN;
8299 }
8300 break;
8301 }
8302
Willy Tarreaubaaee002006-06-26 02:48:02 +02008303 /* first, we will invert the servers list order */
8304 newsrv = NULL;
8305 while (curproxy->srv) {
8306 struct server *next;
8307
8308 next = curproxy->srv->next;
8309 curproxy->srv->next = newsrv;
8310 newsrv = curproxy->srv;
8311 if (!next)
8312 break;
8313 curproxy->srv = next;
8314 }
8315
Willy Tarreau17edc812014-01-03 12:14:34 +01008316 /* Check that no server name conflicts. This causes trouble in the stats.
8317 * We only emit a warning for the first conflict affecting each server,
8318 * in order to avoid combinatory explosion if all servers have the same
8319 * name. We do that only for servers which do not have an explicit ID,
8320 * because these IDs were made also for distinguishing them and we don't
8321 * want to annoy people who correctly manage them.
8322 */
8323 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8324 struct server *other_srv;
8325
8326 if (newsrv->puid)
8327 continue;
8328
8329 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8330 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8331 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8332 newsrv->conf.file, newsrv->conf.line,
8333 proxy_type_str(curproxy), curproxy->id,
8334 newsrv->id, other_srv->conf.line);
8335 break;
8336 }
8337 }
8338 }
8339
Willy Tarreaudd701652010-05-25 23:03:02 +02008340 /* assign automatic UIDs to servers which don't have one yet */
8341 next_id = 1;
8342 newsrv = curproxy->srv;
8343 while (newsrv != NULL) {
8344 if (!newsrv->puid) {
8345 /* server ID not set, use automatic numbering with first
8346 * spare entry starting with next_svid.
8347 */
8348 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8349 newsrv->conf.id.key = newsrv->puid = next_id;
8350 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8351 }
8352 next_id++;
8353 newsrv = newsrv->next;
8354 }
8355
Willy Tarreau20697042007-11-15 23:26:18 +01008356 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008357 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008358
Willy Tarreau62c3be22012-01-20 13:12:32 +01008359 /*
8360 * If this server supports a maxconn parameter, it needs a dedicated
8361 * tasks to fill the emptied slots when a connection leaves.
8362 * Also, resolve deferred tracking dependency if needed.
8363 */
8364 newsrv = curproxy->srv;
8365 while (newsrv != NULL) {
8366 if (newsrv->minconn > newsrv->maxconn) {
8367 /* Only 'minconn' was specified, or it was higher than or equal
8368 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8369 * this will avoid further useless expensive computations.
8370 */
8371 newsrv->maxconn = newsrv->minconn;
8372 } else if (newsrv->maxconn && !newsrv->minconn) {
8373 /* minconn was not specified, so we set it to maxconn */
8374 newsrv->minconn = newsrv->maxconn;
8375 }
8376
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008377#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008378 if (newsrv->use_ssl || newsrv->check.use_ssl)
8379 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008380#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008381
Willy Tarreau2f075e92013-12-03 11:11:34 +01008382 /* set the check type on the server */
8383 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8384
Willy Tarreau62c3be22012-01-20 13:12:32 +01008385 if (newsrv->trackit) {
8386 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008387 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008388 char *pname, *sname;
8389
8390 pname = newsrv->trackit;
8391 sname = strrchr(pname, '/');
8392
8393 if (sname)
8394 *sname++ = '\0';
8395 else {
8396 sname = pname;
8397 pname = NULL;
8398 }
8399
8400 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008401 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008402 if (!px) {
8403 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8404 proxy_type_str(curproxy), curproxy->id,
8405 newsrv->id, pname);
8406 cfgerr++;
8407 goto next_srv;
8408 }
8409 } else
8410 px = curproxy;
8411
8412 srv = findserver(px, sname);
8413 if (!srv) {
8414 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8415 proxy_type_str(curproxy), curproxy->id,
8416 newsrv->id, sname);
8417 cfgerr++;
8418 goto next_srv;
8419 }
8420
Willy Tarreau32091232014-05-16 13:52:00 +02008421 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8422 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8423 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008424 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008425 "tracking as it does not have any check nor agent enabled.\n",
8426 proxy_type_str(curproxy), curproxy->id,
8427 newsrv->id, px->id, srv->id);
8428 cfgerr++;
8429 goto next_srv;
8430 }
8431
8432 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8433
8434 if (loop) {
8435 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8436 "belongs to a tracking chain looping back to %s/%s.\n",
8437 proxy_type_str(curproxy), curproxy->id,
8438 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008439 cfgerr++;
8440 goto next_srv;
8441 }
8442
8443 if (curproxy != px &&
8444 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8445 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8446 "tracking: disable-on-404 option inconsistency.\n",
8447 proxy_type_str(curproxy), curproxy->id,
8448 newsrv->id, px->id, srv->id);
8449 cfgerr++;
8450 goto next_srv;
8451 }
8452
Willy Tarreau62c3be22012-01-20 13:12:32 +01008453 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008454 newsrv->tracknext = srv->trackers;
8455 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008456
8457 free(newsrv->trackit);
8458 newsrv->trackit = NULL;
8459 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008460
8461 /*
8462 * resolve server's resolvers name and update the resolvers pointer
8463 * accordingly
8464 */
8465 if (newsrv->resolvers_id) {
8466 struct dns_resolvers *curr_resolvers;
8467 int found;
8468
8469 found = 0;
8470 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8471 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8472 found = 1;
8473 break;
8474 }
8475 }
8476
8477 if (!found) {
8478 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8479 proxy_type_str(curproxy), curproxy->id,
8480 newsrv->id, newsrv->resolvers_id);
8481 cfgerr++;
8482 } else {
8483 free(newsrv->resolvers_id);
8484 newsrv->resolvers_id = NULL;
8485 if (newsrv->resolution)
8486 newsrv->resolution->resolvers = curr_resolvers;
8487 }
8488 }
8489 else {
8490 /* if no resolvers section associated to this server
8491 * we can clean up the associated resolution structure
8492 */
8493 if (newsrv->resolution) {
8494 free(newsrv->resolution->hostname_dn);
8495 newsrv->resolution->hostname_dn = NULL;
8496 free(newsrv->resolution);
8497 newsrv->resolution = NULL;
8498 }
8499 }
8500
Willy Tarreau62c3be22012-01-20 13:12:32 +01008501 next_srv:
8502 newsrv = newsrv->next;
8503 }
8504
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008505 /* We have to initialize the server lookup mechanism depending
8506 * on what LB algorithm was choosen.
8507 */
8508
8509 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8510 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8511 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008512 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8513 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8514 init_server_map(curproxy);
8515 } else {
8516 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8517 fwrr_init_server_groups(curproxy);
8518 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008519 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008520
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008521 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008522 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8523 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8524 fwlc_init_server_tree(curproxy);
8525 } else {
8526 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8527 fas_init_server_tree(curproxy);
8528 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008529 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008530
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008531 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008532 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8533 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8534 chash_init_server_tree(curproxy);
8535 } else {
8536 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8537 init_server_map(curproxy);
8538 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008539 break;
8540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008541
8542 if (curproxy->options & PR_O_LOGASAP)
8543 curproxy->to_log &= ~LW_BYTES;
8544
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008545 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008546 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8547 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008548 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8549 proxy_type_str(curproxy), curproxy->id);
8550 err_code |= ERR_WARN;
8551 }
8552
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008553 if (curproxy->mode != PR_MODE_HTTP) {
8554 int optnum;
8555
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008556 if (curproxy->uri_auth) {
8557 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8558 proxy_type_str(curproxy), curproxy->id);
8559 err_code |= ERR_WARN;
8560 curproxy->uri_auth = NULL;
8561 }
8562
Willy Tarreau87cf5142011-08-19 22:57:24 +02008563 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008564 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8565 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8566 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008567 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008568 }
8569
8570 if (curproxy->options & PR_O_ORGTO) {
8571 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8572 "originalto", proxy_type_str(curproxy), curproxy->id);
8573 err_code |= ERR_WARN;
8574 curproxy->options &= ~PR_O_ORGTO;
8575 }
8576
8577 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8578 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8579 (curproxy->cap & cfg_opts[optnum].cap) &&
8580 (curproxy->options & cfg_opts[optnum].val)) {
8581 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8582 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8583 err_code |= ERR_WARN;
8584 curproxy->options &= ~cfg_opts[optnum].val;
8585 }
8586 }
8587
8588 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8589 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8590 (curproxy->cap & cfg_opts2[optnum].cap) &&
8591 (curproxy->options2 & cfg_opts2[optnum].val)) {
8592 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8593 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8594 err_code |= ERR_WARN;
8595 curproxy->options2 &= ~cfg_opts2[optnum].val;
8596 }
8597 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008598
Willy Tarreau29fbe512015-08-20 19:35:14 +02008599#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008600 if (curproxy->conn_src.bind_hdr_occ) {
8601 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008602 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008603 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008604 err_code |= ERR_WARN;
8605 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008606#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008607 }
8608
Willy Tarreaubaaee002006-06-26 02:48:02 +02008609 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008610 * ensure that we're not cross-dressing a TCP server into HTTP.
8611 */
8612 newsrv = curproxy->srv;
8613 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008614 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008615 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8616 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008617 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008618 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008619
Willy Tarreau0cec3312011-10-31 13:49:26 +01008620 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8621 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8622 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8623 err_code |= ERR_WARN;
8624 }
8625
Willy Tarreauc93cd162014-05-13 15:54:22 +02008626 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008627 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8628 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8629 err_code |= ERR_WARN;
8630 }
8631
Willy Tarreau29fbe512015-08-20 19:35:14 +02008632#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008633 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8634 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008635 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 +01008636 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008637 err_code |= ERR_WARN;
8638 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008639#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008640 newsrv = newsrv->next;
8641 }
8642
Willy Tarreaue42bd962014-09-16 16:21:19 +02008643 /* check if we have a frontend with "tcp-request content" looking at L7
8644 * with no inspect-delay
8645 */
8646 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8647 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008648 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008649 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008650 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008651 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008652 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008653 break;
8654 }
8655
8656 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8657 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8658 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8659 " This means that these rules will randomly find their contents. This can be fixed by"
8660 " setting the tcp-request inspect-delay.\n",
8661 proxy_type_str(curproxy), curproxy->id);
8662 err_code |= ERR_WARN;
8663 }
8664 }
8665
Christopher Fauletd7c91962015-04-30 11:48:27 +02008666 /* Check filter configuration, if any */
8667 cfgerr += flt_check(curproxy);
8668
Willy Tarreauc1a21672009-08-16 22:37:44 +02008669 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008670 if (!curproxy->accept)
8671 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008672
Willy Tarreauc1a21672009-08-16 22:37:44 +02008673 if (curproxy->tcp_req.inspect_delay ||
8674 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008675 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008676
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008677 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008678 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008679 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008680 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008681
8682 /* both TCP and HTTP must check switching rules */
8683 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008684
8685 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008686 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008687 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8688 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008689 if (curproxy->mode == PR_MODE_HTTP) {
8690 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8691 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8692 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008693 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008694 }
8695
8696 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008697 if (curproxy->tcp_req.inspect_delay ||
8698 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8699 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8700
Emeric Brun97679e72010-09-23 17:56:44 +02008701 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8702 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8703
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008704 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008705 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008706 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008707 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008708
8709 /* If the backend does requires RDP cookie persistence, we have to
8710 * enable the corresponding analyser.
8711 */
8712 if (curproxy->options2 & PR_O2_RDPC_PRST)
8713 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008714
8715 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008716 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008717 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8718 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008719 if (curproxy->mode == PR_MODE_HTTP) {
8720 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8721 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8722 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008723 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008724 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008725 }
8726
8727 /***********************************************************/
8728 /* At this point, target names have already been resolved. */
8729 /***********************************************************/
8730
8731 /* Check multi-process mode compatibility */
8732
8733 if (global.nbproc > 1 && global.stats_fe) {
8734 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8735 unsigned long mask;
8736
8737 mask = nbits(global.nbproc);
8738 if (global.stats_fe->bind_proc)
8739 mask &= global.stats_fe->bind_proc;
8740
8741 if (bind_conf->bind_proc)
8742 mask &= bind_conf->bind_proc;
8743
8744 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008745 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008746 break;
8747 }
8748 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8749 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");
8750 }
8751 }
8752
8753 /* Make each frontend inherit bind-process from its listeners when not specified. */
8754 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8755 if (curproxy->bind_proc)
8756 continue;
8757
8758 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8759 unsigned long mask;
8760
Willy Tarreaue428b082015-05-04 21:57:58 +02008761 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008762 curproxy->bind_proc |= mask;
8763 }
8764
8765 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008766 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008767 }
8768
8769 if (global.stats_fe) {
8770 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8771 unsigned long mask;
8772
Cyril Bonté06181952016-02-24 00:14:54 +01008773 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008774 global.stats_fe->bind_proc |= mask;
8775 }
8776 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008777 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008778 }
8779
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008780 /* propagate bindings from frontends to backends. Don't do it if there
8781 * are any fatal errors as we must not call it with unresolved proxies.
8782 */
8783 if (!cfgerr) {
8784 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8785 if (curproxy->cap & PR_CAP_FE)
8786 propagate_processes(curproxy, NULL);
8787 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008788 }
8789
8790 /* Bind each unbound backend to all processes when not specified. */
8791 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8792 if (curproxy->bind_proc)
8793 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008794 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008795 }
8796
8797 /*******************************************************/
8798 /* At this step, all proxies have a non-null bind_proc */
8799 /*******************************************************/
8800
8801 /* perform the final checks before creating tasks */
8802
8803 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8804 struct listener *listener;
8805 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008806
Emeric Brunc52962f2012-11-15 18:28:02 +01008807#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008808 /* Configure SSL for each bind line.
8809 * Note: if configuration fails at some point, the ->ctx member
8810 * remains NULL so that listeners can later detach.
8811 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008812 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008813 int alloc_ctx;
8814
Emeric Brunc52962f2012-11-15 18:28:02 +01008815 if (!bind_conf->is_ssl) {
8816 if (bind_conf->default_ctx) {
8817 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8818 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8819 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008820 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008821 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008822 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008823 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008824 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008825 cfgerr++;
8826 continue;
8827 }
8828
Emeric Brun8dc60392014-05-09 13:52:00 +02008829 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008830 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008831 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8832 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");
8833 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008834 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008835 cfgerr++;
8836 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008837 }
8838
Emeric Brunfc0421f2012-09-07 17:30:07 +02008839 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008840 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008841
8842 /* initialize CA variables if the certificates generation is enabled */
8843 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008844 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008845#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008846
Willy Tarreaue6b98942007-10-29 01:09:36 +01008847 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008848 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008849 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008850 int nbproc;
8851
8852 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008853 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008854 nbits(global.nbproc));
8855
8856 if (!nbproc) /* no intersection between listener and frontend */
8857 nbproc = 1;
8858
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008859 if (!listener->luid) {
8860 /* listener ID not set, use automatic numbering with first
8861 * spare entry starting with next_luid.
8862 */
8863 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8864 listener->conf.id.key = listener->luid = next_id;
8865 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008866 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008867 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008868
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008869 /* enable separate counters */
8870 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008871 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008872 if (!listener->name)
8873 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008874 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008875
Willy Tarreaue6b98942007-10-29 01:09:36 +01008876 if (curproxy->options & PR_O_TCP_NOLING)
8877 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008878 if (!listener->maxconn)
8879 listener->maxconn = curproxy->maxconn;
8880 if (!listener->backlog)
8881 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008882 if (!listener->maxaccept)
8883 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8884
8885 /* we want to have an optimal behaviour on single process mode to
8886 * maximize the work at once, but in multi-process we want to keep
8887 * some fairness between processes, so we target half of the max
8888 * number of events to be balanced over all the processes the proxy
8889 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8890 * used to disable the limit.
8891 */
8892 if (listener->maxaccept > 0) {
8893 if (nbproc > 1)
8894 listener->maxaccept = (listener->maxaccept + 1) / 2;
8895 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8896 }
8897
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008898 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008899 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008900 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008901 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008902
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008903 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008904 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008905
Willy Tarreau620408f2016-10-21 16:37:51 +02008906 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8907 listener->options |= LI_O_TCP_L5_RULES;
8908
Willy Tarreaude3041d2010-05-31 10:56:17 +02008909 if (curproxy->mon_mask.s_addr)
8910 listener->options |= LI_O_CHK_MONNET;
8911
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008912 /* smart accept mode is automatic in HTTP mode */
8913 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008914 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008915 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8916 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008917 }
8918
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008919 /* Release unused SSL configs */
8920 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8921 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008922 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008923#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008924 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008925 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008926 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008927 free(bind_conf->ca_sign_file);
8928 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008929 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008930 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008931 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008932 if(bind_conf->keys_ref) {
8933 free(bind_conf->keys_ref->filename);
8934 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02008935 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008936 free(bind_conf->keys_ref);
8937 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008938#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008939 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008940
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008941 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008942 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008943 int count, maxproc = 0;
8944
8945 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008946 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008947 if (count > maxproc)
8948 maxproc = count;
8949 }
8950 /* backends have 0, frontends have 1 or more */
8951 if (maxproc != 1)
8952 Warning("Proxy '%s': in multi-process mode, stats will be"
8953 " limited to process assigned to the current request.\n",
8954 curproxy->id);
8955
Willy Tarreau102df612014-05-07 23:56:38 +02008956 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8957 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8958 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008959 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008960 }
Willy Tarreau102df612014-05-07 23:56:38 +02008961 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8962 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8963 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008964 }
8965 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008966
8967 /* create the task associated with the proxy */
8968 curproxy->task = task_new();
8969 if (curproxy->task) {
8970 curproxy->task->context = curproxy;
8971 curproxy->task->process = manage_proxy;
8972 /* no need to queue, it will be done automatically if some
8973 * listener gets limited.
8974 */
8975 curproxy->task->expire = TICK_ETERNITY;
8976 } else {
8977 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8978 curproxy->id);
8979 cfgerr++;
8980 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008981 }
8982
Willy Tarreaufbb78422011-06-05 15:38:35 +02008983 /* automatically compute fullconn if not set. We must not do it in the
8984 * loop above because cross-references are not yet fully resolved.
8985 */
8986 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8987 /* If <fullconn> is not set, let's set it to 10% of the sum of
8988 * the possible incoming frontend's maxconns.
8989 */
8990 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8991 struct proxy *fe;
8992 int total = 0;
8993
8994 /* sum up the number of maxconns of frontends which
8995 * reference this backend at least once or which are
8996 * the same one ('listen').
8997 */
8998 for (fe = proxy; fe; fe = fe->next) {
8999 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009000 int found = 0;
9001
9002 if (!(fe->cap & PR_CAP_FE))
9003 continue;
9004
9005 if (fe == curproxy) /* we're on a "listen" instance */
9006 found = 1;
9007
9008 if (fe->defbe.be == curproxy) /* "default_backend" */
9009 found = 1;
9010
9011 /* check if a "use_backend" rule matches */
9012 if (!found) {
9013 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009014 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009015 found = 1;
9016 break;
9017 }
9018 }
9019 }
9020
Willy Tarreaufbb78422011-06-05 15:38:35 +02009021 /* now we've checked all possible ways to reference a backend
9022 * from a frontend.
9023 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009024 if (!found)
9025 continue;
9026 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009027 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009028 /* we have the sum of the maxconns in <total>. We only
9029 * keep 10% of that sum to set the default fullconn, with
9030 * a hard minimum of 1 (to avoid a divide by zero).
9031 */
9032 curproxy->fullconn = (total + 9) / 10;
9033 if (!curproxy->fullconn)
9034 curproxy->fullconn = 1;
9035 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009036 }
9037
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009038 /*
9039 * Recount currently required checks.
9040 */
9041
9042 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9043 int optnum;
9044
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009045 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9046 if (curproxy->options & cfg_opts[optnum].val)
9047 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009048
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009049 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9050 if (curproxy->options2 & cfg_opts2[optnum].val)
9051 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009052 }
9053
Willy Tarreau0fca4832015-05-01 19:12:05 +02009054 /* compute the required process bindings for the peers */
9055 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9056 if (curproxy->table.peers.p)
9057 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9058
Willy Tarreau122541c2011-09-07 21:24:49 +02009059 if (peers) {
9060 struct peers *curpeers = peers, **last;
9061 struct peer *p, *pb;
9062
Willy Tarreau1e273012015-05-01 19:15:17 +02009063 /* Remove all peers sections which don't have a valid listener,
9064 * which are not used by any table, or which are bound to more
9065 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009066 */
9067 last = &peers;
9068 while (*last) {
9069 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009070
9071 if (curpeers->state == PR_STSTOPPED) {
9072 /* the "disabled" keyword was present */
9073 if (curpeers->peers_fe)
9074 stop_proxy(curpeers->peers_fe);
9075 curpeers->peers_fe = NULL;
9076 }
9077 else if (!curpeers->peers_fe) {
9078 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9079 curpeers->id, localpeer);
9080 }
David Carliere6c39412015-07-02 07:00:17 +00009081 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009082 /* either it's totally stopped or too much used */
9083 if (curpeers->peers_fe->bind_proc) {
9084 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009085 "running in different processes (%d different ones). "
9086 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009087 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009088 cfgerr++;
9089 }
9090 stop_proxy(curpeers->peers_fe);
9091 curpeers->peers_fe = NULL;
9092 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009093 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009094 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009095 last = &curpeers->next;
9096 continue;
9097 }
9098
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009099 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009100 p = curpeers->remote;
9101 while (p) {
9102 pb = p->next;
9103 free(p->id);
9104 free(p);
9105 p = pb;
9106 }
9107
9108 /* Destroy and unlink this curpeers section.
9109 * Note: curpeers is backed up into *last.
9110 */
9111 free(curpeers->id);
9112 curpeers = curpeers->next;
9113 free(*last);
9114 *last = curpeers;
9115 }
9116 }
9117
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009118 /* initialize stick-tables on backend capable proxies. This must not
9119 * be done earlier because the data size may be discovered while parsing
9120 * other proxies.
9121 */
9122 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9123 if (curproxy->state == PR_STSTOPPED)
9124 continue;
9125
9126 if (!stktable_init(&curproxy->table)) {
9127 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9128 cfgerr++;
9129 }
9130 }
9131
Simon Horman0d16a402015-01-30 11:22:58 +09009132 if (mailers) {
9133 struct mailers *curmailers = mailers, **last;
9134 struct mailer *m, *mb;
9135
9136 /* Remove all mailers sections which don't have a valid listener.
9137 * This can happen when a mailers section is never referenced.
9138 */
9139 last = &mailers;
9140 while (*last) {
9141 curmailers = *last;
9142 if (curmailers->users) {
9143 last = &curmailers->next;
9144 continue;
9145 }
9146
9147 Warning("Removing incomplete section 'mailers %s'.\n",
9148 curmailers->id);
9149
9150 m = curmailers->mailer_list;
9151 while (m) {
9152 mb = m->next;
9153 free(m->id);
9154 free(m);
9155 m = mb;
9156 }
9157
9158 /* Destroy and unlink this curmailers section.
9159 * Note: curmailers is backed up into *last.
9160 */
9161 free(curmailers->id);
9162 curmailers = curmailers->next;
9163 free(*last);
9164 *last = curmailers;
9165 }
9166 }
9167
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009168 /* Update server_state_file_name to backend name if backend is supposed to use
9169 * a server-state file locally defined and none has been provided */
9170 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9171 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9172 curproxy->server_state_file_name == NULL)
9173 curproxy->server_state_file_name = strdup(curproxy->id);
9174 }
9175
Willy Tarreau34eb6712011-10-24 18:15:04 +02009176 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009177 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009178 MEM_F_SHARED);
9179
Willy Tarreaubb925012009-07-23 13:36:36 +02009180 if (cfgerr > 0)
9181 err_code |= ERR_ALERT | ERR_FATAL;
9182 out:
9183 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009184}
9185
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009186/*
9187 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9188 * parsing sessions.
9189 */
9190void cfg_register_keywords(struct cfg_kw_list *kwl)
9191{
9192 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9193}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009194
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009195/*
9196 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9197 */
9198void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9199{
9200 LIST_DEL(&kwl->list);
9201 LIST_INIT(&kwl->list);
9202}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009203
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009204/* this function register new section in the haproxy configuration file.
9205 * <section_name> is the name of this new section and <section_parser>
9206 * is the called parser. If two section declaration have the same name,
9207 * only the first declared is used.
9208 */
9209int cfg_register_section(char *section_name,
9210 int (*section_parser)(const char *, int, char **, int))
9211{
9212 struct cfg_section *cs;
9213
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009214 list_for_each_entry(cs, &sections, list) {
9215 if (strcmp(cs->section_name, section_name) == 0) {
9216 Alert("register section '%s': already registered.\n", section_name);
9217 return 0;
9218 }
9219 }
9220
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009221 cs = calloc(1, sizeof(*cs));
9222 if (!cs) {
9223 Alert("register section '%s': out of memory.\n", section_name);
9224 return 0;
9225 }
9226
9227 cs->section_name = section_name;
9228 cs->section_parser = section_parser;
9229
9230 LIST_ADDQ(&sections, &cs->list);
9231
9232 return 1;
9233}
9234
Willy Tarreaubaaee002006-06-26 02:48:02 +02009235/*
David Carlier845efb52015-09-25 11:49:18 +01009236 * free all config section entries
9237 */
9238void cfg_unregister_sections(void)
9239{
9240 struct cfg_section *cs, *ics;
9241
9242 list_for_each_entry_safe(cs, ics, &sections, list) {
9243 LIST_DEL(&cs->list);
9244 free(cs);
9245 }
9246}
9247
Willy Tarreau659fbf02016-05-26 17:55:28 +02009248__attribute__((constructor))
9249static void cfgparse_init(void)
9250{
9251 /* Register internal sections */
9252 cfg_register_section("listen", cfg_parse_listen);
9253 cfg_register_section("frontend", cfg_parse_listen);
9254 cfg_register_section("backend", cfg_parse_listen);
9255 cfg_register_section("defaults", cfg_parse_listen);
9256 cfg_register_section("global", cfg_parse_global);
9257 cfg_register_section("userlist", cfg_parse_users);
9258 cfg_register_section("peers", cfg_parse_peers);
9259 cfg_register_section("mailers", cfg_parse_mailers);
9260 cfg_register_section("namespace_list", cfg_parse_netns);
9261 cfg_register_section("resolvers", cfg_parse_resolvers);
9262}
9263
David Carlier845efb52015-09-25 11:49:18 +01009264/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009265 * Local variables:
9266 * c-indent-level: 8
9267 * c-basic-offset: 8
9268 * End:
9269 */