blob: 3fee54e0db1d34fe8712e4e8f45571c93989da79 [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 */
290 ss = *ss2;
291
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200302 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 l->state = LI_INIT;
304
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100305 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100307 tcpv4_add_listener(l);
308 }
Emeric Bruned760922010-10-22 17:59:25 +0200309 else if (ss.ss_family == AF_INET6) {
310 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
311 tcpv6_add_listener(l);
312 }
313 else {
Emeric Bruned760922010-10-22 17:59:25 +0200314 uxst_add_listener(l);
315 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200317 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100318 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 } /* end for(port) */
320 } /* end while(next) */
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 fail:
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
William Lallemand6e62fb62015-04-28 16:55:23 +0200328/*
329 * Report a fatal Alert when there is too much arguments
330 * The index is the current keyword in args
331 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
332 * Fill err_code with an ERR_ALERT and an ERR_FATAL
333 */
334int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
335{
336 char *kw = NULL;
337 int i;
338
339 if (!*args[index + maxarg + 1])
340 return 0;
341
342 memprintf(&kw, "%s", args[0]);
343 for (i = 1; i <= index; i++) {
344 memprintf(&kw, "%s %s", kw, args[i]);
345 }
346
347 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
348 free(kw);
349 *err_code |= ERR_ALERT | ERR_FATAL;
350 return 1;
351}
352
353/*
354 * same as alertif_too_many_args_idx with a 0 index
355 */
356int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
357{
358 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
359}
360
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request content' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau61d18892009-03-31 10:49:21 +0200374/* Report a warning if a rule is placed after a 'block' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200379 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau5002f572014-04-23 01:32:02 +0200387/* Report a warning if a rule is placed after an 'http_request' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
390int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
391{
392 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
393 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau61d18892009-03-31 10:49:21 +0200400/* Report a warning if a rule is placed after a reqrewrite rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 if (proxy->req_exp) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
413/* Report a warning if a rule is placed after a reqadd rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100418 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
426/* Report a warning if a rule is placed after a redirect rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
433 file, line, arg);
434 return 1;
435 }
436 return 0;
437}
438
439/* Report a warning if a rule is placed after a 'use_backend' rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
Willy Tarreauee445d92014-04-23 01:39:04 +0200452/* Report a warning if a rule is placed after a 'use-server' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
455int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
456{
457 if (!LIST_ISEMPTY(&proxy->server_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200465/* report a warning if a "tcp request connection" rule is dangerously placed */
466int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
467{
468 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
469 warnif_rule_after_block(proxy, file, line, arg) ||
470 warnif_rule_after_http_req(proxy, file, line, arg) ||
471 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
472 warnif_rule_after_reqadd(proxy, file, line, arg) ||
473 warnif_rule_after_redirect(proxy, file, line, arg) ||
474 warnif_rule_after_use_backend(proxy, file, line, arg) ||
475 warnif_rule_after_use_server(proxy, file, line, arg);
476}
477
478/* report a warning if a "tcp request content" rule is dangerously placed */
479int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
480{
481 return warnif_rule_after_block(proxy, file, line, arg) ||
482 warnif_rule_after_http_req(proxy, file, line, arg) ||
483 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
484 warnif_rule_after_reqadd(proxy, file, line, arg) ||
485 warnif_rule_after_redirect(proxy, file, line, arg) ||
486 warnif_rule_after_use_backend(proxy, file, line, arg) ||
487 warnif_rule_after_use_server(proxy, file, line, arg);
488}
489
Willy Tarreau61d18892009-03-31 10:49:21 +0200490/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100491int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200492{
Willy Tarreau5002f572014-04-23 01:32:02 +0200493 return warnif_rule_after_http_req(proxy, file, line, arg) ||
494 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
495 warnif_rule_after_reqadd(proxy, file, line, arg) ||
496 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200497 warnif_rule_after_use_backend(proxy, file, line, arg) ||
498 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200499}
500
501/* report a warning if an http-request rule is dangerously placed */
502int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
503{
Willy Tarreau61d18892009-03-31 10:49:21 +0200504 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
505 warnif_rule_after_reqadd(proxy, file, line, arg) ||
506 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200507 warnif_rule_after_use_backend(proxy, file, line, arg) ||
508 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200509}
510
511/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100512int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200513{
514 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
515 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200516 warnif_rule_after_use_backend(proxy, file, line, arg) ||
517 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200518}
519
520/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100521int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200522{
523 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200524 warnif_rule_after_use_backend(proxy, file, line, arg) ||
525 warnif_rule_after_use_server(proxy, file, line, arg);
526}
527
528/* report a warning if a redirect rule is dangerously placed */
529int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
530{
531 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
532 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100535/* Report it if a request ACL condition uses some keywords that are incompatible
536 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
537 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
538 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200543 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100545 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100546 return 0;
547
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100548 acl = acl_cond_conflicts(cond, where);
549 if (acl) {
550 if (acl->name && *acl->name)
551 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
552 file, line, acl->name, sample_ckp_names(where));
553 else
554 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200555 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556 return ERR_WARN;
557 }
558 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100559 return 0;
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 if (acl->name && *acl->name)
562 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200563 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100564 else
565 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200566 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100567 return ERR_WARN;
568}
569
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200571 * parse a line in a <global> section. Returns the error code, 0 if OK, or
572 * any combination of :
573 * - ERR_ABORT: must abort ASAP
574 * - ERR_FATAL: we can continue parsing but not start the service
575 * - ERR_WARN: a warning has been emitted
576 * - ERR_ALERT: an alert has been emitted
577 * Only the two first ones can stop processing, the two others are just
578 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200580int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581{
Willy Tarreau058e9072009-07-20 09:30:05 +0200582 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200583 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584
585 if (!strcmp(args[0], "global")) { /* new section */
586 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200587 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 else if (!strcmp(args[0], "ca-base")) {
591#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200592 if(alertif_too_many_args(1, file, linenum, args, &err_code))
593 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200594 if (global.ca_base != NULL) {
595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT;
597 goto out;
598 }
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.ca_base = strdup(args[1]);
605#else
606 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
609#endif
610 }
611 else if (!strcmp(args[0], "crt-base")) {
612#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
614 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200615 if (global.crt_base != NULL) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT;
618 goto out;
619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 global.crt_base = strdup(args[1]);
626#else
627 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630#endif
631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 global.mode |= MODE_DAEMON;
636 }
637 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 global.mode |= MODE_DEBUG;
641 }
642 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100657 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100660 global.tune.options &= ~GTUNE_USE_SPLICE;
661 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200662 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200665 global.tune.options &= ~GTUNE_USE_GAI;
666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 global.mode |= MODE_QUIET;
671 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 if (global.tune.maxpollevents != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 }
685 global.tune.maxpollevents = atol(args[1]);
686 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200688 if (alertif_too_many_args(1, file, linenum, args, &err_code))
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 if (global.tune.maxaccept != 0) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 }
700 global.tune.maxaccept = atol(args[1]);
701 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
704 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 global.tune.chksize = atol(args[1]);
711 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100712 else if (!strcmp(args[0], "tune.recv_enough")) {
713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.recv_enough = atol(args[1]);
721 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200722#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200723 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200724 if (alertif_too_many_args(0, file, linenum, args, &err_code))
725 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200726 global.tune.sslprivatecache = 1;
727 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100728 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
730 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200731 if (*(args[1]) == 0) {
732 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
733 err_code |= ERR_ALERT | ERR_FATAL;
734 goto out;
735 }
736 global.tune.sslcachesize = atol(args[1]);
737 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100738 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
739 unsigned int ssllifetime;
740 const char *res;
741
William Lallemand1a748ae2015-05-19 16:37:23 +0200742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
743 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100744 if (*(args[1]) == 0) {
745 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749
750 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
751 if (res) {
752 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
753 file, linenum, *res, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757
758 global.tune.ssllifetime = ssllifetime;
759 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100760 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200761 if (alertif_too_many_args(1, file, linenum, args, &err_code))
762 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
767 }
768 global.tune.ssl_max_record = atol(args[1]);
769 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200770#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200771 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
773 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200774 if (*(args[1]) == 0) {
775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
776 err_code |= ERR_ALERT | ERR_FATAL;
777 goto out;
778 }
779 global.tune.ssl_default_dh_param = atol(args[1]);
780 if (global.tune.ssl_default_dh_param < 1024) {
781 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200786#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200787 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
788 if (alertif_too_many_args(1, file, linenum, args, &err_code))
789 goto out;
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795 global.tune.ssl_ctx_cache = atoi(args[1]);
796 if (global.tune.ssl_ctx_cache < 0) {
797 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200803#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100804 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.buf_limit = atol(args[1]);
813 if (global.tune.buf_limit) {
814 if (global.tune.buf_limit < 3)
815 global.tune.buf_limit = 3;
816 if (global.tune.buf_limit <= global.tune.reserved_bufs)
817 global.tune.buf_limit = global.tune.reserved_bufs + 1;
818 }
819 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100820 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.tune.reserved_bufs = atol(args[1]);
829 if (global.tune.reserved_bufs < 2)
830 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100831 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
832 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100833 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200834 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200835 if (alertif_too_many_args(1, file, linenum, args, &err_code))
836 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200843 if (global.tune.bufsize <= 0) {
844 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100848 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100849 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200850 }
851 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200854 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.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200860 if (global.tune.maxrewrite < 0) {
861 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100866 else if (!strcmp(args[0], "tune.idletimer")) {
867 unsigned int idle;
868 const char *res;
869
William Lallemand1a748ae2015-05-19 16:37:23 +0200870 if (alertif_too_many_args(1, file, linenum, args, &err_code))
871 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100872 if (*(args[1]) == 0) {
873 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877
878 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
879 if (res) {
880 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
881 file, linenum, *res, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885
886 if (idle > 65535) {
887 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.tune.idle_timer = idle;
892 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100893 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200894 if (alertif_too_many_args(1, file, linenum, args, &err_code))
895 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100896 if (global.tune.client_rcvbuf != 0) {
897 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT;
899 goto out;
900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
905 }
906 global.tune.client_rcvbuf = atol(args[1]);
907 }
908 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200909 if (alertif_too_many_args(1, file, linenum, args, &err_code))
910 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100911 if (global.tune.server_rcvbuf != 0) {
912 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT;
914 goto out;
915 }
916 if (*(args[1]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 global.tune.server_rcvbuf = atol(args[1]);
922 }
923 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200924 if (alertif_too_many_args(1, file, linenum, args, &err_code))
925 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100926 if (global.tune.client_sndbuf != 0) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT;
929 goto out;
930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.tune.client_sndbuf = atol(args[1]);
937 }
938 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200939 if (alertif_too_many_args(1, file, linenum, args, &err_code))
940 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100941 if (global.tune.server_sndbuf != 0) {
942 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
943 err_code |= ERR_ALERT;
944 goto out;
945 }
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 global.tune.server_sndbuf = atol(args[1]);
952 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200953 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200954 if (alertif_too_many_args(1, file, linenum, args, &err_code))
955 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200956 if (*(args[1]) == 0) {
957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961 global.tune.pipesize = atol(args[1]);
962 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100963 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200964 if (alertif_too_many_args(1, file, linenum, args, &err_code))
965 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
971 global.tune.cookie_len = atol(args[1]) + 1;
972 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200973 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200974 if (alertif_too_many_args(1, file, linenum, args, &err_code))
975 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981 global.tune.max_http_hdr = atol(args[1]);
982 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100983 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
984#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
986 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100987 if (*args[1]) {
988 global.tune.zlibmemlevel = atoi(args[1]);
989 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
990 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
991 file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995 } else {
996 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
997 file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001#else
1002 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005#endif
1006 }
1007 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1008#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001009 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1010 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001011 if (*args[1]) {
1012 global.tune.zlibwindowsize = atoi(args[1]);
1013 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1014 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1015 file, linenum, args[0]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
1019 } else {
1020 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1021 file, linenum, args[0]);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025#else
1026 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029#endif
1030 }
William Lallemandf3747832012-11-09 12:33:10 +01001031 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001032 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1033 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001034 if (*args[1]) {
1035 global.tune.comp_maxlevel = atoi(args[1]);
1036 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1037 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1038 file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 } else {
1043 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1044 file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001049 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1050 if (*args[1]) {
1051 global.tune.pattern_cache = atoi(args[1]);
1052 if (global.tune.pattern_cache < 0) {
1053 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1054 file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 } else {
1059 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1060 file, linenum, args[0]);
1061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
1063 }
1064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001066 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001069 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001078 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1079 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]);
1080 err_code |= ERR_WARN;
1081 goto out;
1082 }
1083
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 }
1085 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001089 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001098 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1099 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]);
1100 err_code |= ERR_WARN;
1101 goto out;
1102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
Simon Horman98637e52014-06-20 12:30:16 +09001104 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001105 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1106 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001107 global.external_check = 1;
1108 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 /* user/group name handling */
1110 else if (!strcmp(args[0], "user")) {
1111 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001112 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1113 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001114 if (global.uid != 0) {
1115 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001116 err_code |= ERR_ALERT;
1117 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 errno = 0;
1120 ha_user = getpwnam(args[1]);
1121 if (ha_user != NULL) {
1122 global.uid = (int)ha_user->pw_uid;
1123 }
1124 else {
1125 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 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001127 }
1128 }
1129 else if (!strcmp(args[0], "group")) {
1130 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001131 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1132 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001133 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001134 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001137 }
1138 errno = 0;
1139 ha_group = getgrnam(args[1]);
1140 if (ha_group != NULL) {
1141 global.gid = (int)ha_group->gr_gid;
1142 }
1143 else {
1144 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 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001146 }
1147 }
1148 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001150 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001158 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1159 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1160 file, linenum, args[0], LONGBITS, global.nbproc);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 }
1165 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001166 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 if (global.maxconn != 0) {
1169 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001170 err_code |= ERR_ALERT;
1171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 if (*(args[1]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 }
1178 global.maxconn = atol(args[1]);
1179#ifdef SYSTEM_MAXCONN
1180 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1181 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);
1182 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001183 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 }
1185#endif /* SYSTEM_MAXCONN */
1186 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001187 else if (!strcmp(args[0], "maxsslconn")) {
1188#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001189 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1190 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001191 if (*(args[1]) == 0) {
1192 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
1196 global.maxsslconn = atol(args[1]);
1197#else
Emeric Brun0914df82012-10-02 18:45:42 +02001198 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001201#endif
1202 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001203 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1204#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001205 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1206 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001207 if (*(args[1]) == 0) {
1208 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 goto out;
1211 }
1212 free(global.listen_default_ciphers);
1213 global.listen_default_ciphers = strdup(args[1]);
1214#else
1215 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218#endif
1219 }
1220 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1221#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001222 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1223 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 free(global.connect_default_ciphers);
1230 global.connect_default_ciphers = strdup(args[1]);
1231#else
1232 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235#endif
1236 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001237#ifdef USE_OPENSSL
1238#ifndef OPENSSL_NO_DH
1239 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1240 if (*(args[1]) == 0) {
1241 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1246 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250 }
1251#endif
1252#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001253 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 if (strcmp(args[1],"none") == 0)
1262 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1263 else if (strcmp(args[1],"required") == 0)
1264 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1265 else {
1266 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001271 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001274 if (global.cps_lim != 0) {
1275 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1276 err_code |= ERR_ALERT;
1277 goto out;
1278 }
1279 if (*(args[1]) == 0) {
1280 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284 global.cps_lim = atol(args[1]);
1285 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001286 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001287 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1288 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001289 if (global.sps_lim != 0) {
1290 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1291 err_code |= ERR_ALERT;
1292 goto out;
1293 }
1294 if (*(args[1]) == 0) {
1295 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299 global.sps_lim = atol(args[1]);
1300 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001301 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001302 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1303 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001304 if (global.ssl_lim != 0) {
1305 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1306 err_code |= ERR_ALERT;
1307 goto out;
1308 }
1309 if (*(args[1]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 global.ssl_lim = atol(args[1]);
1315 }
William Lallemandd85f9172012-11-09 17:05:39 +01001316 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001317 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1318 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001319 if (*(args[1]) == 0) {
1320 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
1323 }
1324 global.comp_rate_lim = atoi(args[1]) * 1024;
1325 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001326 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001327 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1328 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001329 if (global.maxpipes != 0) {
1330 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001331 err_code |= ERR_ALERT;
1332 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001333 }
1334 if (*(args[1]) == 0) {
1335 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001336 err_code |= ERR_ALERT | ERR_FATAL;
1337 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001338 }
1339 global.maxpipes = atol(args[1]);
1340 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001341 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001342 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1343 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001344 if (*(args[1]) == 0) {
1345 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
1348 }
William Lallemande3a7d992012-11-20 11:25:20 +01001349 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001350 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001351 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001352 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1353 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001354 if (*(args[1]) == 0) {
1355 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
1358 }
1359 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001360 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001361 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001365 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001366
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001368 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 if (global.rlimit_nofile != 0) {
1371 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001372 err_code |= ERR_ALERT;
1373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 }
1375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 }
1380 global.rlimit_nofile = atol(args[1]);
1381 }
1382 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001383 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 if (global.chroot != NULL) {
1386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001387 err_code |= ERR_ALERT;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
1390 if (*(args[1]) == 0) {
1391 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
1393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 }
1395 global.chroot = strdup(args[1]);
1396 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001397 else if (!strcmp(args[0], "description")) {
1398 int i, len=0;
1399 char *d;
1400
1401 if (!*args[1]) {
1402 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1403 file, linenum, args[0]);
1404 err_code |= ERR_ALERT | ERR_FATAL;
1405 goto out;
1406 }
1407
Willy Tarreau348acfe2014-04-14 15:00:39 +02001408 for (i = 1; *args[i]; i++)
1409 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410
1411 if (global.desc)
1412 free(global.desc);
1413
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001414 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001415
Willy Tarreau348acfe2014-04-14 15:00:39 +02001416 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1417 for (i = 2; *args[i]; i++)
1418 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001419 }
1420 else if (!strcmp(args[0], "node")) {
1421 int i;
1422 char c;
1423
William Lallemand1a748ae2015-05-19 16:37:23 +02001424 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1425 goto out;
1426
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001427 for (i=0; args[1][i]; i++) {
1428 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001429 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1430 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001431 break;
1432 }
1433
1434 if (!i || args[1][i]) {
1435 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1436 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1437 file, linenum, args[0]);
1438 err_code |= ERR_ALERT | ERR_FATAL;
1439 goto out;
1440 }
1441
1442 if (global.node)
1443 free(global.node);
1444
1445 global.node = strdup(args[1]);
1446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001448 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 if (global.pidfile != NULL) {
1451 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001452 err_code |= ERR_ALERT;
1453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
1455 if (*(args[1]) == 0) {
1456 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 }
1460 global.pidfile = strdup(args[1]);
1461 }
Emeric Bruned760922010-10-22 17:59:25 +02001462 else if (!strcmp(args[0], "unix-bind")) {
1463 int cur_arg = 1;
1464 while (*(args[cur_arg])) {
1465 if (!strcmp(args[cur_arg], "prefix")) {
1466 if (global.unix_bind.prefix != NULL) {
1467 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1468 err_code |= ERR_ALERT;
1469 cur_arg += 2;
1470 continue;
1471 }
1472
1473 if (*(args[cur_arg+1]) == 0) {
1474 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
1477 }
1478 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1479 cur_arg += 2;
1480 continue;
1481 }
1482
1483 if (!strcmp(args[cur_arg], "mode")) {
1484
1485 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1486 cur_arg += 2;
1487 continue;
1488 }
1489
1490 if (!strcmp(args[cur_arg], "uid")) {
1491
1492 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1493 cur_arg += 2;
1494 continue;
1495 }
1496
1497 if (!strcmp(args[cur_arg], "gid")) {
1498
1499 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1500 cur_arg += 2;
1501 continue;
1502 }
1503
1504 if (!strcmp(args[cur_arg], "user")) {
1505 struct passwd *user;
1506
1507 user = getpwnam(args[cur_arg + 1]);
1508 if (!user) {
1509 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1510 file, linenum, args[0], args[cur_arg + 1 ]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 global.unix_bind.ux.uid = user->pw_uid;
1516 cur_arg += 2;
1517 continue;
1518 }
1519
1520 if (!strcmp(args[cur_arg], "group")) {
1521 struct group *group;
1522
1523 group = getgrnam(args[cur_arg + 1]);
1524 if (!group) {
1525 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1526 file, linenum, args[0], args[cur_arg + 1 ]);
1527 err_code |= ERR_ALERT | ERR_FATAL;
1528 goto out;
1529 }
1530
1531 global.unix_bind.ux.gid = group->gr_gid;
1532 cur_arg += 2;
1533 continue;
1534 }
1535
Willy Tarreaub48f9582011-09-05 01:17:06 +02001536 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001537 file, linenum, args[0]);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
1541 }
William Lallemand0f99e342011-10-12 17:50:54 +02001542 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1543 /* delete previous herited or defined syslog servers */
1544 struct logsrv *back;
1545 struct logsrv *tmp;
1546
1547 if (*(args[1]) != 0) {
1548 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
1551 }
1552
1553 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1554 LIST_DEL(&tmp->list);
1555 free(tmp);
1556 }
1557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001559 struct sockaddr_storage *sk;
1560 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001561 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001562 int arg = 0;
1563 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001564
William Lallemand1a748ae2015-05-19 16:37:23 +02001565 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1566 goto out;
1567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (*(args[1]) == 0 || *(args[2]) == 0) {
1569 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 }
William Lallemand0f99e342011-10-12 17:50:54 +02001573
Vincent Bernat02779b62016-04-03 13:48:43 +02001574 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001575
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 /* just after the address, a length may be specified */
1577 if (strcmp(args[arg+2], "len") == 0) {
1578 len = atoi(args[arg+3]);
1579 if (len < 80 || len > 65535) {
1580 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1581 file, linenum, args[arg+3]);
1582 err_code |= ERR_ALERT | ERR_FATAL;
1583 goto out;
1584 }
1585 logsrv->maxlen = len;
1586
1587 /* skip these two args */
1588 arg += 2;
1589 }
1590 else
1591 logsrv->maxlen = MAX_SYSLOG_LEN;
1592
1593 if (logsrv->maxlen > global.max_syslog_len) {
1594 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001595 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001596 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001597 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001598 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001599 }
1600
Dragan Dosen1322d092015-09-22 16:05:32 +02001601 /* after the length, a format may be specified */
1602 if (strcmp(args[arg+2], "format") == 0) {
1603 logsrv->format = get_log_format(args[arg+3]);
1604 if (logsrv->format < 0) {
1605 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1606 err_code |= ERR_ALERT | ERR_FATAL;
1607 goto out;
1608 }
1609
1610 /* skip these two args */
1611 arg += 2;
1612 }
1613
David Carlier97880bb2016-04-08 10:35:26 +01001614 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1615 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001616 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001617 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001618
Willy Tarreau18324f52014-06-27 18:10:07 +02001619 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001620 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001621 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001622 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001623 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 }
1625
William Lallemand0f99e342011-10-12 17:50:54 +02001626 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001627 if (*(args[arg+3])) {
1628 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001629 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001630 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001631 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001632 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 }
1634 }
1635
William Lallemand0f99e342011-10-12 17:50:54 +02001636 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001637 if (*(args[arg+4])) {
1638 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001639 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001640 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001642 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001643 }
1644 }
1645
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001646 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001647 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001648 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001649 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001650 free(logsrv);
1651 goto out;
1652 }
1653 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001654
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001655 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001656 if (port1 != port2) {
1657 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1658 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001659 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001660 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001661 goto out;
1662 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001663
William Lallemand0f99e342011-10-12 17:50:54 +02001664 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001665 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001666 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668
William Lallemand0f99e342011-10-12 17:50:54 +02001669 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001670 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001671 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1672 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001673
1674 if (global.log_send_hostname != NULL) {
1675 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1676 err_code |= ERR_ALERT;
1677 goto out;
1678 }
1679
1680 if (*(args[1]))
1681 name = args[1];
1682 else
1683 name = hostname;
1684
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001685 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001686 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001687 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001688 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1689 if (global.server_state_base != NULL) {
1690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1691 err_code |= ERR_ALERT;
1692 goto out;
1693 }
1694
1695 if (!*(args[1])) {
1696 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1697 err_code |= ERR_FATAL;
1698 goto out;
1699 }
1700
1701 global.server_state_base = strdup(args[1]);
1702 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001703 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1704 if (global.server_state_file != NULL) {
1705 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1706 err_code |= ERR_ALERT;
1707 goto out;
1708 }
1709
1710 if (!*(args[1])) {
1711 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1712 err_code |= ERR_FATAL;
1713 goto out;
1714 }
1715
1716 global.server_state_file = strdup(args[1]);
1717 }
Kevinm48936af2010-12-22 16:08:21 +00001718 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1720 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001721 if (*(args[1]) == 0) {
1722 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001726 chunk_destroy(&global.log_tag);
1727 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001728 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001729 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1731 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001732 if (global.spread_checks != 0) {
1733 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001734 err_code |= ERR_ALERT;
1735 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001736 }
1737 if (*(args[1]) == 0) {
1738 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001739 err_code |= ERR_ALERT | ERR_FATAL;
1740 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001741 }
1742 global.spread_checks = atol(args[1]);
1743 if (global.spread_checks < 0 || global.spread_checks > 50) {
1744 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001745 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001748 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1749 const char *err;
1750 unsigned int val;
1751
William Lallemand1a748ae2015-05-19 16:37:23 +02001752 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1753 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001754 if (*(args[1]) == 0) {
1755 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
1759
1760 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1761 if (err) {
1762 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 }
1765 global.max_spread_checks = val;
1766 if (global.max_spread_checks < 0) {
1767 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1768 err_code |= ERR_ALERT | ERR_FATAL;
1769 }
1770 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001771 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1772#ifdef USE_CPU_AFFINITY
1773 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001774 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001775 unsigned long cpus = 0;
1776
1777 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001778 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001779 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001780 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001781 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001782 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001783 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001784 proc = atol(args[1]);
1785 if (proc >= 1 && proc <= LONGBITS)
1786 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001787 }
1788
1789 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001790 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",
1791 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001792 err_code |= ERR_ALERT | ERR_FATAL;
1793 goto out;
1794 }
1795
1796 cur_arg = 2;
1797 while (*args[cur_arg]) {
1798 unsigned int low, high;
1799
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001800 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001801 char *dash = strchr(args[cur_arg], '-');
1802
1803 low = high = str2uic(args[cur_arg]);
1804 if (dash)
1805 high = str2uic(dash + 1);
1806
1807 if (high < low) {
1808 unsigned int swap = low;
1809 low = high;
1810 high = swap;
1811 }
1812
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001813 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001814 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001815 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
1819
1820 while (low <= high)
1821 cpus |= 1UL << low++;
1822 }
1823 else {
1824 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1825 file, linenum, args[0], args[cur_arg]);
1826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
1828 }
1829 cur_arg++;
1830 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001831 for (i = 0; i < LONGBITS; i++)
1832 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001833 global.cpu_map[i] = cpus;
1834#else
1835 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
1838#endif
1839 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001840 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1841 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1842 goto out;
1843
1844 if (*(args[2]) == 0) {
1845 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
1848 }
1849
1850 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1851 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1852 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856 }
1857 else if (!strcmp(args[0], "unsetenv")) {
1858 int arg;
1859
1860 if (*(args[1]) == 0) {
1861 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
1865
1866 for (arg = 1; *args[arg]; arg++) {
1867 if (unsetenv(args[arg]) != 0) {
1868 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872 }
1873 }
1874 else if (!strcmp(args[0], "resetenv")) {
1875 extern char **environ;
1876 char **env = environ;
1877
1878 /* args contain variable names to keep, one per argument */
1879 while (*env) {
1880 int arg;
1881
1882 /* look for current variable in among all those we want to keep */
1883 for (arg = 1; *args[arg]; arg++) {
1884 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1885 (*env)[strlen(args[arg])] == '=')
1886 break;
1887 }
1888
1889 /* delete this variable */
1890 if (!*args[arg]) {
1891 char *delim = strchr(*env, '=');
1892
1893 if (!delim || delim - *env >= trash.size) {
1894 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1895 err_code |= ERR_ALERT | ERR_FATAL;
1896 goto out;
1897 }
1898
1899 memcpy(trash.str, *env, delim - *env);
1900 trash.str[delim - *env] = 0;
1901
1902 if (unsetenv(trash.str) != 0) {
1903 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
1906 }
1907 }
1908 else
1909 env++;
1910 }
1911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001913 struct cfg_kw_list *kwl;
1914 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001915 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001916
1917 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1918 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1919 if (kwl->kw[index].section != CFG_GLOBAL)
1920 continue;
1921 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001922 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001923 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001924 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001925 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001926 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001927 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001928 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001929 err_code |= ERR_WARN;
1930 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001931 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001932 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001933 }
1934 }
1935 }
1936
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001938 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001940
Willy Tarreau058e9072009-07-20 09:30:05 +02001941 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001942 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001943 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944}
1945
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001946void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001948 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 defproxy.mode = PR_MODE_TCP;
1950 defproxy.state = PR_STNEW;
1951 defproxy.maxconn = cfg_maxpconn;
1952 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001953 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001954
Simon Horman66183002013-02-23 10:16:43 +09001955 defproxy.defsrv.check.inter = DEF_CHKINTR;
1956 defproxy.defsrv.check.fastinter = 0;
1957 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001958 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1959 defproxy.defsrv.agent.fastinter = 0;
1960 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001961 defproxy.defsrv.check.rise = DEF_RISETIME;
1962 defproxy.defsrv.check.fall = DEF_FALLTIME;
1963 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1964 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001965 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001966 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001967 defproxy.defsrv.maxqueue = 0;
1968 defproxy.defsrv.minconn = 0;
1969 defproxy.defsrv.maxconn = 0;
1970 defproxy.defsrv.slowstart = 0;
1971 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1972 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1973 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001974
1975 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001976 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977}
1978
Willy Tarreauade5ec42010-01-28 19:33:49 +01001979
Willy Tarreau63af98d2014-05-18 08:11:41 +02001980/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1981 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1982 * ERR_FATAL in case of error.
1983 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001984static int create_cond_regex_rule(const char *file, int line,
1985 struct proxy *px, int dir, int action, int flags,
1986 const char *cmd, const char *reg, const char *repl,
1987 const char **cond_start)
1988{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001989 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001990 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001991 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001992 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001993 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001994 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001995 int cs;
1996 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001997
1998 if (px == &defproxy) {
1999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002000 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002001 goto err;
2002 }
2003
2004 if (*reg == 0) {
2005 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002006 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002007 goto err;
2008 }
2009
2010 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002011 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002012
Willy Tarreau5321c422010-01-28 20:35:13 +01002013 if (cond_start &&
2014 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002015 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2016 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2017 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002018 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002019 goto err;
2020 }
2021 }
2022 else if (cond_start && **cond_start) {
2023 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2024 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002025 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002026 goto err;
2027 }
2028
Willy Tarreau63af98d2014-05-18 08:11:41 +02002029 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002030 (dir == SMP_OPT_DIR_REQ) ?
2031 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2032 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2033 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002034
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002035 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002036 if (!preg) {
2037 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002038 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002039 goto err;
2040 }
2041
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002042 cs = !(flags & REG_ICASE);
2043 cap = !(flags & REG_NOSUB);
2044 error = NULL;
2045 if (!regex_comp(reg, preg, cs, cap, &error)) {
2046 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2047 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002048 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002049 goto err;
2050 }
2051
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002052 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002053 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002054 if (repl && err) {
2055 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2056 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002057 ret_code |= ERR_ALERT | ERR_FATAL;
2058 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002059 }
2060
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002061 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002062 ret_code |= ERR_WARN;
2063
2064 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002065
Willy Tarreau63af98d2014-05-18 08:11:41 +02002066 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002067 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002068 err:
2069 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002070 free(errmsg);
2071 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002072}
2073
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074/*
William Lallemand51097192015-04-14 16:35:22 +02002075 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002076 * Returns the error code, 0 if OK, or any combination of :
2077 * - ERR_ABORT: must abort ASAP
2078 * - ERR_FATAL: we can continue parsing but not start the service
2079 * - ERR_WARN: a warning has been emitted
2080 * - ERR_ALERT: an alert has been emitted
2081 * Only the two first ones can stop processing, the two others are just
2082 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002084int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2085{
2086 static struct peers *curpeers = NULL;
2087 struct peer *newpeer = NULL;
2088 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002089 struct bind_conf *bind_conf;
2090 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002091 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002092 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002093
2094 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002095 if (!*args[1]) {
2096 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002097 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002098 goto out;
2099 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002100
William Lallemand6e62fb62015-04-28 16:55:23 +02002101 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2102 goto out;
2103
Emeric Brun32da3c42010-09-23 18:39:19 +02002104 err = invalid_char(args[1]);
2105 if (err) {
2106 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2107 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002108 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002109 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 }
2111
2112 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2113 /*
2114 * If there are two proxies with the same name only following
2115 * combinations are allowed:
2116 */
2117 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002118 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 +02002119 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002121 }
2122 }
2123
Vincent Bernat02779b62016-04-03 13:48:43 +02002124 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002125 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2126 err_code |= ERR_ALERT | ERR_ABORT;
2127 goto out;
2128 }
2129
2130 curpeers->next = peers;
2131 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002132 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002133 curpeers->conf.line = linenum;
2134 curpeers->last_change = now.tv_sec;
2135 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002136 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002137 }
2138 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002139 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002140 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002141 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002142
2143 if (!*args[2]) {
2144 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2145 file, linenum, args[0]);
2146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
2148 }
2149
2150 err = invalid_char(args[1]);
2151 if (err) {
2152 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2153 file, linenum, *err, args[1]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
2157
Vincent Bernat02779b62016-04-03 13:48:43 +02002158 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002159 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2160 err_code |= ERR_ALERT | ERR_ABORT;
2161 goto out;
2162 }
2163
2164 /* the peers are linked backwards first */
2165 curpeers->count++;
2166 newpeer->next = curpeers->remote;
2167 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002168 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002169 newpeer->conf.line = linenum;
2170
2171 newpeer->last_change = now.tv_sec;
2172 newpeer->id = strdup(args[1]);
2173
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002174 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002175 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002176 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002179 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002180
2181 proto = protocol_by_family(sk->ss_family);
2182 if (!proto || !proto->connect) {
2183 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2184 file, linenum, args[0], args[1]);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
2187 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002188
2189 if (port1 != port2) {
2190 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2191 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
Willy Tarreau2aa38802013-02-20 19:20:59 +01002196 if (!port1) {
2197 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2198 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002202
Emeric Brun32da3c42010-09-23 18:39:19 +02002203 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002204 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002205 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002206 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002207
Emeric Brun32da3c42010-09-23 18:39:19 +02002208 if (strcmp(newpeer->id, localpeer) == 0) {
2209 /* Current is local peer, it define a frontend */
2210 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002211 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002212
2213 if (!curpeers->peers_fe) {
2214 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2215 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2216 err_code |= ERR_ALERT | ERR_ABORT;
2217 goto out;
2218 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002219
Willy Tarreau237250c2011-07-29 01:49:03 +02002220 init_new_proxy(curpeers->peers_fe);
2221 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002222 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002223 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2224 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002225 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002226
2227 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2228
Willy Tarreau902636f2013-03-10 19:44:48 +01002229 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2230 if (errmsg && *errmsg) {
2231 indent_msg(&errmsg, 2);
2232 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002233 }
2234 else
2235 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2236 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002237 err_code |= ERR_FATAL;
2238 goto out;
2239 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002240
2241 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002242 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002243 l->maxconn = curpeers->peers_fe->maxconn;
2244 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002245 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002246 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002247 l->analysers |= curpeers->peers_fe->fe_req_ana;
2248 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002249 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2250 global.maxsock += l->maxconn;
2251 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002252 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002253 else {
2254 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2255 file, linenum, args[0], args[1],
2256 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2257 err_code |= ERR_FATAL;
2258 goto out;
2259 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002260 }
2261 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002262 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2263 curpeers->state = PR_STSTOPPED;
2264 }
2265 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2266 curpeers->state = PR_STNEW;
2267 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002268 else if (*args[0] != 0) {
2269 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
2273
2274out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002275 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002276 return err_code;
2277}
2278
Baptiste Assmann325137d2015-04-13 23:40:55 +02002279/*
2280 * Parse a <resolvers> section.
2281 * Returns the error code, 0 if OK, or any combination of :
2282 * - ERR_ABORT: must abort ASAP
2283 * - ERR_FATAL: we can continue parsing but not start the service
2284 * - ERR_WARN: a warning has been emitted
2285 * - ERR_ALERT: an alert has been emitted
2286 * Only the two first ones can stop processing, the two others are just
2287 * indicators.
2288 */
2289int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2290{
2291 static struct dns_resolvers *curr_resolvers = NULL;
2292 struct dns_nameserver *newnameserver = NULL;
2293 const char *err;
2294 int err_code = 0;
2295 char *errmsg = NULL;
2296
2297 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2298 if (!*args[1]) {
2299 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2300 err_code |= ERR_ALERT | ERR_ABORT;
2301 goto out;
2302 }
2303
2304 err = invalid_char(args[1]);
2305 if (err) {
2306 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2307 file, linenum, *err, args[0], args[1]);
2308 err_code |= ERR_ALERT | ERR_ABORT;
2309 goto out;
2310 }
2311
2312 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2313 /* Error if two resolvers owns the same name */
2314 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2315 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2316 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2317 err_code |= ERR_ALERT | ERR_ABORT;
2318 }
2319 }
2320
Vincent Bernat02779b62016-04-03 13:48:43 +02002321 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002322 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2323 err_code |= ERR_ALERT | ERR_ABORT;
2324 goto out;
2325 }
2326
2327 /* default values */
2328 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2329 curr_resolvers->conf.file = strdup(file);
2330 curr_resolvers->conf.line = linenum;
2331 curr_resolvers->id = strdup(args[1]);
2332 curr_resolvers->query_ids = EB_ROOT;
2333 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002334 curr_resolvers->hold.valid = 10000;
2335 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002336 curr_resolvers->resolve_retries = 3;
2337 LIST_INIT(&curr_resolvers->nameserver_list);
2338 LIST_INIT(&curr_resolvers->curr_resolution);
2339 }
2340 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2341 struct sockaddr_storage *sk;
2342 int port1, port2;
2343 struct protocol *proto;
2344
2345 if (!*args[2]) {
2346 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2347 file, linenum, args[0]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351
2352 err = invalid_char(args[1]);
2353 if (err) {
2354 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2355 file, linenum, *err, args[1]);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
2358 }
2359
Baptiste Assmanna315c552015-11-02 22:55:49 +01002360 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2361 /* Error if two resolvers owns the same name */
2362 if (strcmp(newnameserver->id, args[1]) == 0) {
2363 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2364 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 }
2367 }
2368
Vincent Bernat02779b62016-04-03 13:48:43 +02002369 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002370 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2371 err_code |= ERR_ALERT | ERR_ABORT;
2372 goto out;
2373 }
2374
2375 /* the nameservers are linked backward first */
2376 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2377 curr_resolvers->count_nameservers++;
2378 newnameserver->resolvers = curr_resolvers;
2379 newnameserver->conf.file = strdup(file);
2380 newnameserver->conf.line = linenum;
2381 newnameserver->id = strdup(args[1]);
2382
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002383 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002384 if (!sk) {
2385 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
2389
2390 proto = protocol_by_family(sk->ss_family);
2391 if (!proto || !proto->connect) {
2392 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2393 file, linenum, args[0], args[1]);
2394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
2396 }
2397
2398 if (port1 != port2) {
2399 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2400 file, linenum, args[0], args[1], args[2]);
2401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
2403 }
2404
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002405 if (!port1 && !port2) {
2406 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2407 file, linenum, args[0], args[1]);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
Baptiste Assmann325137d2015-04-13 23:40:55 +02002412 newnameserver->addr = *sk;
2413 }
2414 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2415 const char *res;
2416 unsigned int time;
2417
2418 if (!*args[2]) {
2419 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2420 file, linenum, args[0]);
2421 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
2424 }
2425 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2426 if (res) {
2427 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2428 file, linenum, *res, args[0]);
2429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
2431 }
2432 if (strcmp(args[1], "valid") == 0)
2433 curr_resolvers->hold.valid = time;
2434 else {
2435 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2436 file, linenum, args[0], args[1]);
2437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
2439 }
2440
2441 }
2442 else if (strcmp(args[0], "resolve_retries") == 0) {
2443 if (!*args[1]) {
2444 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2445 file, linenum, args[0]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449 curr_resolvers->resolve_retries = atoi(args[1]);
2450 }
2451 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002452 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002453 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2454 file, linenum, args[0]);
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002458 else if (strcmp(args[1], "retry") == 0) {
2459 const char *res;
2460 unsigned int timeout_retry;
2461
2462 if (!*args[2]) {
2463 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2464 file, linenum, args[0], args[1]);
2465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
2467 }
2468 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2469 if (res) {
2470 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2471 file, linenum, *res, args[0], args[1]);
2472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
2474 }
2475 curr_resolvers->timeout.retry = timeout_retry;
2476 }
2477 else {
2478 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2479 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
2482 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002483 } /* neither "nameserver" nor "resolvers" */
2484 else if (*args[0] != 0) {
2485 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
2488 }
2489
2490 out:
2491 free(errmsg);
2492 return err_code;
2493}
Simon Horman0d16a402015-01-30 11:22:58 +09002494
2495/*
William Lallemand51097192015-04-14 16:35:22 +02002496 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002497 * Returns the error code, 0 if OK, or any combination of :
2498 * - ERR_ABORT: must abort ASAP
2499 * - ERR_FATAL: we can continue parsing but not start the service
2500 * - ERR_WARN: a warning has been emitted
2501 * - ERR_ALERT: an alert has been emitted
2502 * Only the two first ones can stop processing, the two others are just
2503 * indicators.
2504 */
2505int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2506{
2507 static struct mailers *curmailers = NULL;
2508 struct mailer *newmailer = NULL;
2509 const char *err;
2510 int err_code = 0;
2511 char *errmsg = NULL;
2512
2513 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2514 if (!*args[1]) {
2515 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2516 err_code |= ERR_ALERT | ERR_ABORT;
2517 goto out;
2518 }
2519
2520 err = invalid_char(args[1]);
2521 if (err) {
2522 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2523 file, linenum, *err, args[0], args[1]);
2524 err_code |= ERR_ALERT | ERR_ABORT;
2525 goto out;
2526 }
2527
2528 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2529 /*
2530 * If there are two proxies with the same name only following
2531 * combinations are allowed:
2532 */
2533 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002534 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 +09002535 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002537 }
2538 }
2539
Vincent Bernat02779b62016-04-03 13:48:43 +02002540 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002541 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2542 err_code |= ERR_ALERT | ERR_ABORT;
2543 goto out;
2544 }
2545
2546 curmailers->next = mailers;
2547 mailers = curmailers;
2548 curmailers->conf.file = strdup(file);
2549 curmailers->conf.line = linenum;
2550 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002551 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2552 * But need enough time so that timeouts don't occur
2553 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002554 }
2555 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2556 struct sockaddr_storage *sk;
2557 int port1, port2;
2558 struct protocol *proto;
2559
2560 if (!*args[2]) {
2561 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2562 file, linenum, args[0]);
2563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
2565 }
2566
2567 err = invalid_char(args[1]);
2568 if (err) {
2569 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2570 file, linenum, *err, args[1]);
2571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
2573 }
2574
Vincent Bernat02779b62016-04-03 13:48:43 +02002575 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002576 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2577 err_code |= ERR_ALERT | ERR_ABORT;
2578 goto out;
2579 }
2580
2581 /* the mailers are linked backwards first */
2582 curmailers->count++;
2583 newmailer->next = curmailers->mailer_list;
2584 curmailers->mailer_list = newmailer;
2585 newmailer->mailers = curmailers;
2586 newmailer->conf.file = strdup(file);
2587 newmailer->conf.line = linenum;
2588
2589 newmailer->id = strdup(args[1]);
2590
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002591 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002592 if (!sk) {
2593 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
2596 }
2597
2598 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002599 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2600 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002601 file, linenum, args[0], args[1]);
2602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
2604 }
2605
2606 if (port1 != port2) {
2607 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2608 file, linenum, args[0], args[1], args[2]);
2609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
2611 }
2612
2613 if (!port1) {
2614 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2615 file, linenum, args[0], args[1], args[2]);
2616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
2618 }
2619
2620 newmailer->addr = *sk;
2621 newmailer->proto = proto;
2622 newmailer->xprt = &raw_sock;
2623 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002624 }
2625 else if (strcmp(args[0], "timeout") == 0) {
2626 if (!*args[1]) {
2627 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2628 file, linenum, args[0]);
2629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
2631 }
2632 else if (strcmp(args[1], "mail") == 0) {
2633 const char *res;
2634 unsigned int timeout_mail;
2635 if (!*args[2]) {
2636 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2637 file, linenum, args[0], args[1]);
2638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
2641 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2642 if (res) {
2643 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2644 file, linenum, *res, args[0]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648 if (timeout_mail <= 0) {
2649 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653 curmailers->timeout.mail = timeout_mail;
2654 } else {
2655 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2656 file, linenum, args[0], args[1]);
2657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
2659 }
2660 }
Simon Horman0d16a402015-01-30 11:22:58 +09002661 else if (*args[0] != 0) {
2662 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667out:
2668 free(errmsg);
2669 return err_code;
2670}
2671
Simon Horman9dc49962015-01-30 11:22:59 +09002672static void free_email_alert(struct proxy *p)
2673{
2674 free(p->email_alert.mailers.name);
2675 p->email_alert.mailers.name = NULL;
2676 free(p->email_alert.from);
2677 p->email_alert.from = NULL;
2678 free(p->email_alert.to);
2679 p->email_alert.to = NULL;
2680 free(p->email_alert.myhostname);
2681 p->email_alert.myhostname = NULL;
2682}
2683
Willy Tarreau3842f002009-06-14 11:39:52 +02002684int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685{
2686 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002687 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002688 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002689 int rc;
2690 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002691 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002692 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002693 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002694 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002695 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696
Willy Tarreau977b8e42006-12-29 14:19:17 +01002697 if (!strcmp(args[0], "listen"))
2698 rc = PR_CAP_LISTEN;
2699 else if (!strcmp(args[0], "frontend"))
2700 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002701 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002703 else
2704 rc = PR_CAP_NONE;
2705
2706 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 if (!*args[1]) {
2708 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2709 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002711 err_code |= ERR_ALERT | ERR_ABORT;
2712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002714
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002715 err = invalid_char(args[1]);
2716 if (err) {
2717 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2718 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002720 }
2721
Willy Tarreau8f50b682015-05-26 11:45:02 +02002722 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2723 if (curproxy) {
2724 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2725 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2726 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002728 }
2729
Vincent Bernat02779b62016-04-03 13:48:43 +02002730 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_ALERT | ERR_ABORT;
2733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002735
Willy Tarreau97cb7802010-01-03 20:23:58 +01002736 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 curproxy->next = proxy;
2738 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002739 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2740 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002741 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002744 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745
William Lallemand6e62fb62015-04-28 16:55:23 +02002746 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2747 if (curproxy->cap & PR_CAP_FE)
2748 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 }
2751
2752 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002753 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002754 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002755
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002758 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002759 curproxy->no_options = defproxy.no_options;
2760 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002761 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002762 curproxy->except_net = defproxy.except_net;
2763 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002764 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002765 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002767 if (defproxy.fwdfor_hdr_len) {
2768 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2769 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2770 }
2771
Willy Tarreaub86db342009-11-30 11:50:16 +01002772 if (defproxy.orgto_hdr_len) {
2773 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2774 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2775 }
2776
Mark Lamourinec2247f02012-01-04 13:02:01 -05002777 if (defproxy.server_id_hdr_len) {
2778 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2779 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2780 }
2781
Willy Tarreau977b8e42006-12-29 14:19:17 +01002782 if (curproxy->cap & PR_CAP_FE) {
2783 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002784 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002785 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786
2787 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002788 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2789 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002790
2791 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793
Willy Tarreau977b8e42006-12-29 14:19:17 +01002794 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002795 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002796 curproxy->fullconn = defproxy.fullconn;
2797 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002798 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002799 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002801 if (defproxy.check_req) {
2802 curproxy->check_req = calloc(1, defproxy.check_len);
2803 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2804 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002805 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002807 if (defproxy.expect_str) {
2808 curproxy->expect_str = strdup(defproxy.expect_str);
2809 if (defproxy.expect_regex) {
2810 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002811 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2812 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002813 }
2814 }
2815
Willy Tarreau67402132012-05-31 20:40:20 +02002816 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002817 if (defproxy.cookie_name)
2818 curproxy->cookie_name = strdup(defproxy.cookie_name);
2819 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002820 if (defproxy.cookie_domain)
2821 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002822
Willy Tarreau31936852010-10-06 16:59:56 +02002823 if (defproxy.cookie_maxidle)
2824 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2825
2826 if (defproxy.cookie_maxlife)
2827 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2828
Emeric Brun647caf12009-06-30 17:57:00 +02002829 if (defproxy.rdp_cookie_name)
2830 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2831 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2832
Willy Tarreau01732802007-11-01 22:48:15 +01002833 if (defproxy.url_param_name)
2834 curproxy->url_param_name = strdup(defproxy.url_param_name);
2835 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002836
Benoitaffb4812009-03-25 13:02:10 +01002837 if (defproxy.hh_name)
2838 curproxy->hh_name = strdup(defproxy.hh_name);
2839 curproxy->hh_len = defproxy.hh_len;
2840 curproxy->hh_match_domain = defproxy.hh_match_domain;
2841
Willy Tarreauef9a3602012-12-08 22:29:20 +01002842 if (defproxy.conn_src.iface_name)
2843 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2844 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002845 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002846#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002847 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002848#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002849 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002852 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853 if (defproxy.capture_name)
2854 curproxy->capture_name = strdup(defproxy.capture_name);
2855 curproxy->capture_namelen = defproxy.capture_namelen;
2856 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002860 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002861 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002862 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002863 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002864 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865 curproxy->mon_net = defproxy.mon_net;
2866 curproxy->mon_mask = defproxy.mon_mask;
2867 if (defproxy.monitor_uri)
2868 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2869 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002870 if (defproxy.defbe.name)
2871 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002872
2873 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002874 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2875 if (curproxy->conf.logformat_string &&
2876 curproxy->conf.logformat_string != default_http_log_format &&
2877 curproxy->conf.logformat_string != default_tcp_log_format &&
2878 curproxy->conf.logformat_string != clf_http_log_format)
2879 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2880
2881 if (defproxy.conf.lfs_file) {
2882 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2883 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2884 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002885
2886 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2887 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2888 if (curproxy->conf.logformat_sd_string &&
2889 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2890 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2891
2892 if (defproxy.conf.lfsd_file) {
2893 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2894 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2895 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002896 }
2897
2898 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002899 curproxy->timeout.connect = defproxy.timeout.connect;
2900 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002901 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002902 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002903 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002904 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002905 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002906 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002907 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002908 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002909 }
2910
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002912 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002913
2914 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002915 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002916 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002917 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002918 LIST_INIT(&node->list);
2919 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2920 }
2921
Willy Tarreau62a61232013-04-12 18:13:46 +02002922 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2923 if (curproxy->conf.uniqueid_format_string)
2924 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2925
Dragan Dosen43885c72015-10-01 13:18:13 +02002926 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002927
Willy Tarreau62a61232013-04-12 18:13:46 +02002928 if (defproxy.conf.uif_file) {
2929 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2930 curproxy->conf.uif_line = defproxy.conf.uif_line;
2931 }
William Lallemanda73203e2012-03-12 12:48:57 +01002932
2933 /* copy default header unique id */
2934 if (defproxy.header_unique_id)
2935 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2936
William Lallemand82fe75c2012-10-23 10:25:10 +02002937 /* default compression options */
2938 if (defproxy.comp != NULL) {
2939 curproxy->comp = calloc(1, sizeof(struct comp));
2940 curproxy->comp->algos = defproxy.comp->algos;
2941 curproxy->comp->types = defproxy.comp->types;
2942 }
2943
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002945 curproxy->conf.used_listener_id = EB_ROOT;
2946 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002947
Simon Horman98637e52014-06-20 12:30:16 +09002948 if (defproxy.check_path)
2949 curproxy->check_path = strdup(defproxy.check_path);
2950 if (defproxy.check_command)
2951 curproxy->check_command = strdup(defproxy.check_command);
2952
Simon Horman9dc49962015-01-30 11:22:59 +09002953 if (defproxy.email_alert.mailers.name)
2954 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2955 if (defproxy.email_alert.from)
2956 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2957 if (defproxy.email_alert.to)
2958 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2959 if (defproxy.email_alert.myhostname)
2960 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002961 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002962 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002963
Willy Tarreau93893792009-07-23 13:19:11 +02002964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 }
2966 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2967 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002968 /* FIXME-20070101: we should do this too at the end of the
2969 * config parsing to free all default values.
2970 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002971 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2972 err_code |= ERR_ABORT;
2973 goto out;
2974 }
2975
Willy Tarreaua534fea2008-08-03 12:19:50 +02002976 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002977 free(defproxy.check_command);
2978 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002979 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002980 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002981 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002982 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002983 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002984 free(defproxy.capture_name);
2985 free(defproxy.monitor_uri);
2986 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002987 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002988 free(defproxy.fwdfor_hdr_name);
2989 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002990 free(defproxy.orgto_hdr_name);
2991 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002992 free(defproxy.server_id_hdr_name);
2993 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002994 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002995 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002996 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002997 free(defproxy.expect_regex);
2998 defproxy.expect_regex = NULL;
2999 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003000
Willy Tarreau62a61232013-04-12 18:13:46 +02003001 if (defproxy.conf.logformat_string != default_http_log_format &&
3002 defproxy.conf.logformat_string != default_tcp_log_format &&
3003 defproxy.conf.logformat_string != clf_http_log_format)
3004 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003005
Willy Tarreau62a61232013-04-12 18:13:46 +02003006 free(defproxy.conf.uniqueid_format_string);
3007 free(defproxy.conf.lfs_file);
3008 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003009 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003010 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003011
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003012 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3013 free(defproxy.conf.logformat_sd_string);
3014 free(defproxy.conf.lfsd_file);
3015
Willy Tarreaua534fea2008-08-03 12:19:50 +02003016 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003017 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003018
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 /* we cannot free uri_auth because it might already be used */
3020 init_default_instance();
3021 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003022 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3023 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003024 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 }
3027 else if (curproxy == NULL) {
3028 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003032
3033 /* update the current file and line being parsed */
3034 curproxy->conf.args.file = curproxy->conf.file;
3035 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003036
3037 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003038 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3039 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3040 if (err_code & ERR_FATAL)
3041 goto out;
3042 }
3043 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003044 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003045 int cur_arg;
3046
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 if (curproxy == &defproxy) {
3048 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003052 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054
Willy Tarreau24709282013-03-10 21:32:12 +01003055 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003056 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003061
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003062 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003063
3064 /* use default settings for unix sockets */
3065 bind_conf->ux.uid = global.unix_bind.ux.uid;
3066 bind_conf->ux.gid = global.unix_bind.ux.gid;
3067 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003068
3069 /* NOTE: the following line might create several listeners if there
3070 * are comma-separated IPs or port ranges. So all further processing
3071 * will have to be applied to all listeners created after last_listen.
3072 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003073 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3074 if (errmsg && *errmsg) {
3075 indent_msg(&errmsg, 2);
3076 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003077 }
3078 else
3079 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3080 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003084
Willy Tarreau4348fad2012-09-20 16:48:07 +02003085 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3086 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003087 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003088 }
3089
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003090 cur_arg = 2;
3091 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003092 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003093 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003094 char *err;
3095
Willy Tarreau26982662012-09-12 23:17:10 +02003096 kw = bind_find_kw(args[cur_arg]);
3097 if (kw) {
3098 char *err = NULL;
3099 int code;
3100
3101 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003102 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3103 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003104 cur_arg += 1 + kw->skip ;
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
Willy Tarreau4348fad2012-09-20 16:48:07 +02003109 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003110 err_code |= code;
3111
3112 if (code) {
3113 if (err && *err) {
3114 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003115 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003116 }
3117 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003118 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3119 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003120 if (code & ERR_FATAL) {
3121 free(err);
3122 cur_arg += 1 + kw->skip;
3123 goto out;
3124 }
3125 }
3126 free(err);
3127 cur_arg += 1 + kw->skip;
3128 continue;
3129 }
3130
Willy Tarreau8638f482012-09-18 18:01:17 +02003131 err = NULL;
3132 if (!bind_dumped) {
3133 bind_dump_kws(&err);
3134 indent_msg(&err, 4);
3135 bind_dumped = 1;
3136 }
3137
3138 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3139 file, linenum, args[0], args[1], args[cur_arg],
3140 err ? " Registered keywords :" : "", err ? err : "");
3141 free(err);
3142
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003145 }
Willy Tarreau93893792009-07-23 13:19:11 +02003146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003149 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3151 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003155 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003157
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 /* flush useless bits */
3159 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003162 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003163 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003165
William Lallemanddf1425a2015-04-28 20:17:49 +02003166 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3167 goto out;
3168
Willy Tarreau1c47f852006-07-09 08:22:27 +02003169 if (!*args[1]) {
3170 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3171 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003174 }
3175
Willy Tarreaua534fea2008-08-03 12:19:50 +02003176 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003177 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003178 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003179 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003180 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3181
Willy Tarreau93893792009-07-23 13:19:11 +02003182 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003185 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3186 goto out;
3187
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3189 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3190 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3191 else {
3192 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003197 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003198 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003199
3200 if (curproxy == &defproxy) {
3201 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3202 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003205 }
3206
William Lallemanddf1425a2015-04-28 20:17:49 +02003207 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3208 goto out;
3209
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003210 if (!*args[1]) {
3211 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3212 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003215 }
3216
3217 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003218 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003219 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003220
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003221 if (curproxy->uuid <= 0) {
3222 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003223 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003226 }
3227
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003228 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3229 if (node) {
3230 struct proxy *target = container_of(node, struct proxy, conf.id);
3231 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3232 file, linenum, proxy_type_str(curproxy), curproxy->id,
3233 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
3237 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003238 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003239 else if (!strcmp(args[0], "description")) {
3240 int i, len=0;
3241 char *d;
3242
Cyril Bonté99ed3272010-01-24 23:29:44 +01003243 if (curproxy == &defproxy) {
3244 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3245 file, linenum, args[0]);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
3249
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003250 if (!*args[1]) {
3251 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3252 file, linenum, args[0]);
3253 return -1;
3254 }
3255
Willy Tarreau348acfe2014-04-14 15:00:39 +02003256 for (i = 1; *args[i]; i++)
3257 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003258
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003259 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003260 curproxy->desc = d;
3261
Willy Tarreau348acfe2014-04-14 15:00:39 +02003262 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3263 for (i = 2; *args[i]; i++)
3264 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003265
3266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003268 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 curproxy->state = PR_STSTOPPED;
3271 }
3272 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003273 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 curproxy->state = PR_STNEW;
3276 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003277 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3278 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003279 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003280
3281 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003282 unsigned int low, high;
3283
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003284 if (strcmp(args[cur_arg], "all") == 0) {
3285 set = 0;
3286 break;
3287 }
3288 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003289 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003290 }
3291 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003292 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003293 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003294 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003295 char *dash = strchr(args[cur_arg], '-');
3296
3297 low = high = str2uic(args[cur_arg]);
3298 if (dash)
3299 high = str2uic(dash + 1);
3300
3301 if (high < low) {
3302 unsigned int swap = low;
3303 low = high;
3304 high = swap;
3305 }
3306
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003307 if (low < 1 || high > LONGBITS) {
3308 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3309 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003312 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003313 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003314 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003315 }
3316 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003317 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3318 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003321 }
3322 cur_arg++;
3323 }
3324 curproxy->bind_proc = set;
3325 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003326 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003327 if (curproxy == &defproxy) {
3328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003331 }
3332
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003333 err = invalid_char(args[1]);
3334 if (err) {
3335 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3336 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003338 }
3339
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003340 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003341 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3342 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003345 }
3346 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3348 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349
Willy Tarreau977b8e42006-12-29 14:19:17 +01003350 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003352
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 if (*(args[1]) == 0) {
3354 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3355 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003359
Willy Tarreau67402132012-05-31 20:40:20 +02003360 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003361 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003362 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003363 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 curproxy->cookie_name = strdup(args[1]);
3365 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003366
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 cur_arg = 2;
3368 while (*(args[cur_arg])) {
3369 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003370 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 }
3372 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003373 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
3375 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003376 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 }
3378 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003379 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 }
3381 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003382 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003384 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003385 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003388 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003390 else if (!strcmp(args[cur_arg], "httponly")) {
3391 curproxy->ck_opts |= PR_CK_HTTPONLY;
3392 }
3393 else if (!strcmp(args[cur_arg], "secure")) {
3394 curproxy->ck_opts |= PR_CK_SECURE;
3395 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003396 else if (!strcmp(args[cur_arg], "domain")) {
3397 if (!*args[cur_arg + 1]) {
3398 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3399 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003402 }
3403
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003404 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003405 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003406 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3407 " dots nor does not start with a dot."
3408 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003409 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003410 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003411 }
3412
3413 err = invalid_domainchar(args[cur_arg + 1]);
3414 if (err) {
3415 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3416 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003419 }
3420
Willy Tarreau68a897b2009-12-03 23:28:34 +01003421 if (!curproxy->cookie_domain) {
3422 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3423 } else {
3424 /* one domain was already specified, add another one by
3425 * building the string which will be returned along with
3426 * the cookie.
3427 */
3428 char *new_ptr;
3429 int new_len = strlen(curproxy->cookie_domain) +
3430 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3431 new_ptr = malloc(new_len);
3432 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3433 free(curproxy->cookie_domain);
3434 curproxy->cookie_domain = new_ptr;
3435 }
Willy Tarreau31936852010-10-06 16:59:56 +02003436 cur_arg++;
3437 }
3438 else if (!strcmp(args[cur_arg], "maxidle")) {
3439 unsigned int maxidle;
3440 const char *res;
3441
3442 if (!*args[cur_arg + 1]) {
3443 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3444 file, linenum, args[cur_arg]);
3445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
3447 }
3448
3449 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3450 if (res) {
3451 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3452 file, linenum, *res, args[cur_arg]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 curproxy->cookie_maxidle = maxidle;
3457 cur_arg++;
3458 }
3459 else if (!strcmp(args[cur_arg], "maxlife")) {
3460 unsigned int maxlife;
3461 const char *res;
3462
3463 if (!*args[cur_arg + 1]) {
3464 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3465 file, linenum, args[cur_arg]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
3469
3470 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3471 if (res) {
3472 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3473 file, linenum, *res, args[cur_arg]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
3477 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003478 cur_arg++;
3479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003481 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 +02003482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003485 }
3486 cur_arg++;
3487 }
Willy Tarreau67402132012-05-31 20:40:20 +02003488 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3490 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 }
3493
Willy Tarreau67402132012-05-31 20:40:20 +02003494 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3496 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003499
Willy Tarreau67402132012-05-31 20:40:20 +02003500 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003501 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3502 file, linenum);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003506 else if (!strcmp(args[0], "email-alert")) {
3507 if (*(args[1]) == 0) {
3508 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3509 file, linenum, args[0]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513
3514 if (!strcmp(args[1], "from")) {
3515 if (*(args[1]) == 0) {
3516 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3517 file, linenum, args[1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
3521 free(curproxy->email_alert.from);
3522 curproxy->email_alert.from = strdup(args[2]);
3523 }
3524 else if (!strcmp(args[1], "mailers")) {
3525 if (*(args[1]) == 0) {
3526 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3527 file, linenum, args[1]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531 free(curproxy->email_alert.mailers.name);
3532 curproxy->email_alert.mailers.name = strdup(args[2]);
3533 }
3534 else if (!strcmp(args[1], "myhostname")) {
3535 if (*(args[1]) == 0) {
3536 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3537 file, linenum, args[1]);
3538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
3540 }
3541 free(curproxy->email_alert.myhostname);
3542 curproxy->email_alert.myhostname = strdup(args[2]);
3543 }
Simon Horman64e34162015-02-06 11:11:57 +09003544 else if (!strcmp(args[1], "level")) {
3545 curproxy->email_alert.level = get_log_level(args[2]);
3546 if (curproxy->email_alert.level < 0) {
3547 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3548 file, linenum, args[1], args[2]);
3549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
3551 }
3552 }
Simon Horman9dc49962015-01-30 11:22:59 +09003553 else if (!strcmp(args[1], "to")) {
3554 if (*(args[1]) == 0) {
3555 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3556 file, linenum, args[1]);
3557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
3559 }
3560 free(curproxy->email_alert.to);
3561 curproxy->email_alert.to = strdup(args[2]);
3562 }
3563 else {
3564 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3565 file, linenum, args[1]);
3566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
3568 }
Simon Horman64e34162015-02-06 11:11:57 +09003569 /* Indicate that the email_alert is at least partially configured */
3570 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003571 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003572 else if (!strcmp(args[0], "external-check")) {
3573 if (*(args[1]) == 0) {
3574 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3575 file, linenum, args[0]);
3576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
3578 }
3579
3580 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003581 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003582 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003583 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003584 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3585 file, linenum, args[1]);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588 }
3589 free(curproxy->check_command);
3590 curproxy->check_command = strdup(args[2]);
3591 }
3592 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003593 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003594 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003595 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003596 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3597 file, linenum, args[1]);
3598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
3600 }
3601 free(curproxy->check_path);
3602 curproxy->check_path = strdup(args[2]);
3603 }
3604 else {
3605 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3606 file, linenum, args[1]);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
3609 }
3610 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003611 else if (!strcmp(args[0], "persist")) { /* persist */
3612 if (*(args[1]) == 0) {
3613 Alert("parsing [%s:%d] : missing persist method.\n",
3614 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003617 }
3618
3619 if (!strncmp(args[1], "rdp-cookie", 10)) {
3620 curproxy->options2 |= PR_O2_RDPC_PRST;
3621
Emeric Brunb982a3d2010-01-04 15:45:53 +01003622 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003623 const char *beg, *end;
3624
3625 beg = args[1] + 11;
3626 end = strchr(beg, ')');
3627
William Lallemanddf1425a2015-04-28 20:17:49 +02003628 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3629 goto out;
3630
Emeric Brun647caf12009-06-30 17:57:00 +02003631 if (!end || end == beg) {
3632 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3633 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003636 }
3637
3638 free(curproxy->rdp_cookie_name);
3639 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3640 curproxy->rdp_cookie_len = end-beg;
3641 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003642 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003643 free(curproxy->rdp_cookie_name);
3644 curproxy->rdp_cookie_name = strdup("msts");
3645 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3646 }
3647 else { /* syntax */
3648 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3649 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003652 }
3653 }
3654 else {
3655 Alert("parsing [%s:%d] : unknown persist method.\n",
3656 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003659 }
3660 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003662 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003666 else if (!strcmp(args[0], "load-server-state-from-file")) {
3667 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3668 err_code |= ERR_WARN;
3669 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3670 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3671 }
3672 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3673 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3674 }
3675 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3676 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3677 }
3678 else {
3679 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3680 file, linenum, args[0], args[1]);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
3684 }
3685 else if (!strcmp(args[0], "server-state-file-name")) {
3686 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3687 err_code |= ERR_WARN;
3688 if (*(args[1]) == 0) {
3689 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3690 file, linenum, args[0]);
3691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
3693 }
3694 else if (!strcmp(args[1], "use-backend-name"))
3695 curproxy->server_state_file_name = strdup(curproxy->id);
3696 else
3697 curproxy->server_state_file_name = strdup(args[1]);
3698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003700 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003701 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003702
Willy Tarreaubaaee002006-06-26 02:48:02 +02003703 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003704 if (curproxy == &defproxy) {
3705 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
3708 }
3709
William Lallemand1a748ae2015-05-19 16:37:23 +02003710 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3711 goto out;
3712
Willy Tarreaubaaee002006-06-26 02:48:02 +02003713 if (*(args[4]) == 0) {
3714 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003719 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 curproxy->capture_name = strdup(args[2]);
3721 curproxy->capture_namelen = strlen(curproxy->capture_name);
3722 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 curproxy->to_log |= LW_COOKIE;
3724 }
3725 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3726 struct cap_hdr *hdr;
3727
3728 if (curproxy == &defproxy) {
3729 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 +02003730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 }
3733
William Lallemand1a748ae2015-05-19 16:37:23 +02003734 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3735 goto out;
3736
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3738 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3739 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
3743
Vincent Bernat02779b62016-04-03 13:48:43 +02003744 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 hdr->next = curproxy->req_cap;
3746 hdr->name = strdup(args[3]);
3747 hdr->namelen = strlen(args[3]);
3748 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003749 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 hdr->index = curproxy->nb_req_cap++;
3751 curproxy->req_cap = hdr;
3752 curproxy->to_log |= LW_REQHDR;
3753 }
3754 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3755 struct cap_hdr *hdr;
3756
3757 if (curproxy == &defproxy) {
3758 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 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 }
3762
William Lallemand1a748ae2015-05-19 16:37:23 +02003763 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3764 goto out;
3765
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3767 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3768 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003772 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 hdr->next = curproxy->rsp_cap;
3774 hdr->name = strdup(args[3]);
3775 hdr->namelen = strlen(args[3]);
3776 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003777 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 hdr->index = curproxy->nb_rsp_cap++;
3779 curproxy->rsp_cap = hdr;
3780 curproxy->to_log |= LW_RSPHDR;
3781 }
3782 else {
3783 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3784 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 }
3788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003792
William Lallemanddf1425a2015-04-28 20:17:49 +02003793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3794 goto out;
3795
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 if (*(args[1]) == 0) {
3797 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3798 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 }
3802 curproxy->conn_retries = atol(args[1]);
3803 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003804 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003805 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003806
3807 if (curproxy == &defproxy) {
3808 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
3811 }
3812
Willy Tarreau20b0de52012-12-24 15:45:22 +01003813 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003814 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003815 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3816 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3817 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3818 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003819 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 +01003820 file, linenum, args[0]);
3821 err_code |= ERR_WARN;
3822 }
3823
Willy Tarreauff011f22011-01-06 17:51:27 +01003824 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003825
Willy Tarreauff011f22011-01-06 17:51:27 +01003826 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003827 err_code |= ERR_ALERT | ERR_ABORT;
3828 goto out;
3829 }
3830
Willy Tarreau5002f572014-04-23 01:32:02 +02003831 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003832 err_code |= warnif_cond_conflicts(rule->cond,
3833 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3834 file, linenum);
3835
Willy Tarreauff011f22011-01-06 17:51:27 +01003836 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003837 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003838 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003839 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003840
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
3847 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003848 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003849 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3850 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003851 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3852 file, linenum, args[0]);
3853 err_code |= ERR_WARN;
3854 }
3855
3856 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3857
3858 if (!rule) {
3859 err_code |= ERR_ALERT | ERR_ABORT;
3860 goto out;
3861 }
3862
3863 err_code |= warnif_cond_conflicts(rule->cond,
3864 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3865 file, linenum);
3866
3867 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3868 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003869 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3870 /* set the header name and length into the proxy structure */
3871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3872 err_code |= ERR_WARN;
3873
3874 if (!*args[1]) {
3875 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3876 file, linenum, args[0]);
3877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
3879 }
3880
3881 /* set the desired header name */
3882 free(curproxy->server_id_hdr_name);
3883 curproxy->server_id_hdr_name = strdup(args[1]);
3884 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3885 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003886 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003887 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003888
Willy Tarreaub099aca2008-10-12 17:26:37 +02003889 if (curproxy == &defproxy) {
3890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003893 }
3894
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003895 /* emulate "block" using "http-request block". Since these rules are supposed to
3896 * be processed before all http-request rules, we put them into their own list
3897 * and will insert them at the end.
3898 */
3899 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3900 if (!rule) {
3901 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003902 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003903 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003904 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3905 err_code |= warnif_cond_conflicts(rule->cond,
3906 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3907 file, linenum);
3908 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003909
3910 if (!already_warned(WARN_BLOCK_DEPRECATED))
3911 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]);
3912
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003913 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003914 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003915 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003916
Cyril Bonté99ed3272010-01-24 23:29:44 +01003917 if (curproxy == &defproxy) {
3918 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922
Willy Tarreaube4653b2015-05-28 15:26:58 +02003923 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003924 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3925 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003928 }
3929
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003930 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003931 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003932 err_code |= warnif_cond_conflicts(rule->cond,
3933 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3934 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003935 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003936 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003937 struct switching_rule *rule;
3938
Willy Tarreaub099aca2008-10-12 17:26:37 +02003939 if (curproxy == &defproxy) {
3940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003943 }
3944
Willy Tarreau55ea7572007-06-17 19:56:27 +02003945 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003947
3948 if (*(args[1]) == 0) {
3949 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003952 }
3953
Willy Tarreauf51658d2014-04-23 01:21:56 +02003954 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3955 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3956 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3957 file, linenum, errmsg);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003961
Willy Tarreauf51658d2014-04-23 01:21:56 +02003962 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003963 }
3964
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003965 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02003966 rule->cond = cond;
3967 rule->be.name = strdup(args[1]);
3968 LIST_INIT(&rule->list);
3969 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3970 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003971 else if (strcmp(args[0], "use-server") == 0) {
3972 struct server_rule *rule;
3973
3974 if (curproxy == &defproxy) {
3975 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
3978 }
3979
3980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3981 err_code |= ERR_WARN;
3982
3983 if (*(args[1]) == 0) {
3984 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
3988
3989 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3990 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3991 file, linenum, args[0]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
3995
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003996 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3997 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3998 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
4002
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004003 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004004
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004005 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004006 rule->cond = cond;
4007 rule->srv.name = strdup(args[1]);
4008 LIST_INIT(&rule->list);
4009 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4010 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4011 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004012 else if ((!strcmp(args[0], "force-persist")) ||
4013 (!strcmp(args[0], "ignore-persist"))) {
4014 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004015
4016 if (curproxy == &defproxy) {
4017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021
4022 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4023 err_code |= ERR_WARN;
4024
Willy Tarreauef6494c2010-01-28 17:12:36 +01004025 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004026 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4027 file, linenum, args[0]);
4028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
4030 }
4031
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004032 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4033 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4034 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
4038
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004039 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4040 * where force-persist is applied.
4041 */
4042 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004043
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004044 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004045 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004046 if (!strcmp(args[0], "force-persist")) {
4047 rule->type = PERSIST_TYPE_FORCE;
4048 } else {
4049 rule->type = PERSIST_TYPE_IGNORE;
4050 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004051 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004052 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004053 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004054 else if (!strcmp(args[0], "stick-table")) {
4055 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004056 struct proxy *other;
4057
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004058 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004059 if (other) {
4060 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4061 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004065
Emeric Brun32da3c42010-09-23 18:39:19 +02004066 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004067 curproxy->table.type = (unsigned int)-1;
4068 while (*args[myidx]) {
4069 const char *err;
4070
4071 if (strcmp(args[myidx], "size") == 0) {
4072 myidx++;
4073 if (!*(args[myidx])) {
4074 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4075 file, linenum, args[myidx-1]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4080 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4081 file, linenum, *err, args[myidx-1]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004085 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004086 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004087 else if (strcmp(args[myidx], "peers") == 0) {
4088 myidx++;
Godbach50523162013-12-11 19:48:57 +08004089 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004090 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4091 file, linenum, args[myidx-1]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
Godbach50523162013-12-11 19:48:57 +08004094 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004095 curproxy->table.peers.name = strdup(args[myidx++]);
4096 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004097 else if (strcmp(args[myidx], "expire") == 0) {
4098 myidx++;
4099 if (!*(args[myidx])) {
4100 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4101 file, linenum, args[myidx-1]);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
4104 }
4105 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4106 if (err) {
4107 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4108 file, linenum, *err, args[myidx-1]);
4109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
4111 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004112 if (val > INT_MAX) {
4113 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4114 file, linenum, val);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004118 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004119 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004120 }
4121 else if (strcmp(args[myidx], "nopurge") == 0) {
4122 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004123 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 }
4125 else if (strcmp(args[myidx], "type") == 0) {
4126 myidx++;
4127 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4128 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4129 file, linenum, args[myidx]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004133 /* myidx already points to next arg */
4134 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004135 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004136 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004137 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004138
4139 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004140 nw = args[myidx];
4141 while (*nw) {
4142 /* the "store" keyword supports a comma-separated list */
4143 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004144 sa = NULL; /* store arg */
4145 while (*nw && *nw != ',') {
4146 if (*nw == '(') {
4147 *nw = 0;
4148 sa = ++nw;
4149 while (*nw != ')') {
4150 if (!*nw) {
4151 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4152 file, linenum, args[0], cw);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156 nw++;
4157 }
4158 *nw = '\0';
4159 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004160 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004161 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004162 if (*nw)
4163 *nw++ = '\0';
4164 type = stktable_get_data_type(cw);
4165 if (type < 0) {
4166 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4167 file, linenum, args[0], cw);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
Willy Tarreauac782882010-06-20 10:41:54 +02004171
4172 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4173 switch (err) {
4174 case PE_NONE: break;
4175 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004176 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4177 file, linenum, args[0], cw);
4178 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004179 break;
4180
4181 case PE_ARG_MISSING:
4182 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4183 file, linenum, args[0], cw);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186
4187 case PE_ARG_NOT_USED:
4188 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4189 file, linenum, args[0], cw);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192
4193 default:
4194 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4195 file, linenum, args[0], cw);
4196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004198 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004199 }
4200 myidx++;
4201 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004202 else {
4203 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4204 file, linenum, args[myidx]);
4205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004207 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004208 }
4209
4210 if (!curproxy->table.size) {
4211 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4212 file, linenum);
4213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
4215 }
4216
4217 if (curproxy->table.type == (unsigned int)-1) {
4218 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4219 file, linenum);
4220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
4222 }
4223 }
4224 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004225 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004226 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004227 int myidx = 0;
4228 const char *name = NULL;
4229 int flags;
4230
4231 if (curproxy == &defproxy) {
4232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
4235 }
4236
4237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4238 err_code |= ERR_WARN;
4239 goto out;
4240 }
4241
4242 myidx++;
4243 if ((strcmp(args[myidx], "store") == 0) ||
4244 (strcmp(args[myidx], "store-request") == 0)) {
4245 myidx++;
4246 flags = STK_IS_STORE;
4247 }
4248 else if (strcmp(args[myidx], "store-response") == 0) {
4249 myidx++;
4250 flags = STK_IS_STORE | STK_ON_RSP;
4251 }
4252 else if (strcmp(args[myidx], "match") == 0) {
4253 myidx++;
4254 flags = STK_IS_MATCH;
4255 }
4256 else if (strcmp(args[myidx], "on") == 0) {
4257 myidx++;
4258 flags = STK_IS_MATCH | STK_IS_STORE;
4259 }
4260 else {
4261 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265
4266 if (*(args[myidx]) == 0) {
4267 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004272 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004273 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004274 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004275 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
4280 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004281 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4282 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4283 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004284 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004285 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004286 goto out;
4287 }
4288 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004289 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4290 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4291 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004292 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004293 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004294 goto out;
4295 }
4296 }
4297
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004298 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004299 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004300
Emeric Brunb982a3d2010-01-04 15:45:53 +01004301 if (strcmp(args[myidx], "table") == 0) {
4302 myidx++;
4303 name = args[myidx++];
4304 }
4305
Willy Tarreauef6494c2010-01-28 17:12:36 +01004306 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004307 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4308 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4309 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004310 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004311 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004312 goto out;
4313 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004314 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004315 else if (*(args[myidx])) {
4316 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4317 file, linenum, args[0], args[myidx]);
4318 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004319 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004320 goto out;
4321 }
Emeric Brun97679e72010-09-23 17:56:44 +02004322 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004323 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004324 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004325 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004326
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004327 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004328 rule->cond = cond;
4329 rule->expr = expr;
4330 rule->flags = flags;
4331 rule->table.name = name ? strdup(name) : NULL;
4332 LIST_INIT(&rule->list);
4333 if (flags & STK_ON_RSP)
4334 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4335 else
4336 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 else if (!strcmp(args[0], "stats")) {
4339 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4340 curproxy->uri_auth = NULL; /* we must detach from the default config */
4341
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004342 if (!*args[1]) {
4343 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004344 } else if (!strcmp(args[1], "admin")) {
4345 struct stats_admin_rule *rule;
4346
4347 if (curproxy == &defproxy) {
4348 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
4353 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4354 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4355 err_code |= ERR_ALERT | ERR_ABORT;
4356 goto out;
4357 }
4358
4359 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4360 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4361 file, linenum, args[0], args[1]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004365 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4366 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4367 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004372 err_code |= warnif_cond_conflicts(cond,
4373 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4374 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004375
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004376 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004377 rule->cond = cond;
4378 LIST_INIT(&rule->list);
4379 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 } else if (!strcmp(args[1], "uri")) {
4381 if (*(args[2]) == 0) {
4382 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_ABORT;
4388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 }
4390 } else if (!strcmp(args[1], "realm")) {
4391 if (*(args[2]) == 0) {
4392 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4396 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_ABORT;
4398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004400 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004401 unsigned interval;
4402
4403 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4404 if (err) {
4405 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4406 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004409 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4410 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004411 err_code |= ERR_ALERT | ERR_ABORT;
4412 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004413 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004414 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004415 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004416
4417 if (curproxy == &defproxy) {
4418 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422
4423 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4424 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4425 err_code |= ERR_ALERT | ERR_ABORT;
4426 goto out;
4427 }
4428
Willy Tarreauff011f22011-01-06 17:51:27 +01004429 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004430 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004431 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4432 file, linenum, args[0]);
4433 err_code |= ERR_WARN;
4434 }
4435
Willy Tarreauff011f22011-01-06 17:51:27 +01004436 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004437
Willy Tarreauff011f22011-01-06 17:51:27 +01004438 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004439 err_code |= ERR_ALERT | ERR_ABORT;
4440 goto out;
4441 }
4442
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004443 err_code |= warnif_cond_conflicts(rule->cond,
4444 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4445 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004446 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004447
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 } else if (!strcmp(args[1], "auth")) {
4449 if (*(args[2]) == 0) {
4450 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4454 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_ABORT;
4456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 }
4458 } else if (!strcmp(args[1], "scope")) {
4459 if (*(args[2]) == 0) {
4460 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4464 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_ALERT | ERR_ABORT;
4466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 }
4468 } else if (!strcmp(args[1], "enable")) {
4469 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_ABORT;
4472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004474 } else if (!strcmp(args[1], "hide-version")) {
4475 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_ABORT;
4478 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004479 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004480 } else if (!strcmp(args[1], "show-legends")) {
4481 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4482 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4483 err_code |= ERR_ALERT | ERR_ABORT;
4484 goto out;
4485 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004486 } else if (!strcmp(args[1], "show-node")) {
4487
4488 if (*args[2]) {
4489 int i;
4490 char c;
4491
4492 for (i=0; args[2][i]; i++) {
4493 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004494 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4495 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004496 break;
4497 }
4498
4499 if (!i || args[2][i]) {
4500 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4501 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4502 file, linenum, args[0], args[1]);
4503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
4505 }
4506 }
4507
4508 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4509 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4510 err_code |= ERR_ALERT | ERR_ABORT;
4511 goto out;
4512 }
4513 } else if (!strcmp(args[1], "show-desc")) {
4514 char *desc = NULL;
4515
4516 if (*args[2]) {
4517 int i, len=0;
4518 char *d;
4519
Willy Tarreau348acfe2014-04-14 15:00:39 +02004520 for (i = 2; *args[i]; i++)
4521 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004522
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004523 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004524
Willy Tarreau348acfe2014-04-14 15:00:39 +02004525 d += snprintf(d, desc + len - d, "%s", args[2]);
4526 for (i = 3; *args[i]; i++)
4527 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004528 }
4529
4530 if (!*args[2] && !global.desc)
4531 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4532 file, linenum, args[1]);
4533 else {
4534 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4535 free(desc);
4536 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4537 err_code |= ERR_ALERT | ERR_ABORT;
4538 goto out;
4539 }
4540 free(desc);
4541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004543stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004544 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 +01004545 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548 }
4549 }
4550 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004551 int optnum;
4552
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004553 if (*(args[1]) == '\0') {
4554 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004559
4560 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4561 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004562 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4563 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4564 file, linenum, cfg_opts[optnum].name);
4565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004568 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4569 goto out;
4570
Willy Tarreau93893792009-07-23 13:19:11 +02004571 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4572 err_code |= ERR_WARN;
4573 goto out;
4574 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004575
Willy Tarreau3842f002009-06-14 11:39:52 +02004576 curproxy->no_options &= ~cfg_opts[optnum].val;
4577 curproxy->options &= ~cfg_opts[optnum].val;
4578
4579 switch (kwm) {
4580 case KWM_STD:
4581 curproxy->options |= cfg_opts[optnum].val;
4582 break;
4583 case KWM_NO:
4584 curproxy->no_options |= cfg_opts[optnum].val;
4585 break;
4586 case KWM_DEF: /* already cleared */
4587 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004588 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004589
Willy Tarreau93893792009-07-23 13:19:11 +02004590 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004591 }
4592 }
4593
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004594 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4595 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004596 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4597 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4598 file, linenum, cfg_opts2[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;
Willy Tarreau93893792009-07-23 13:19:11 +02004604 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4605 err_code |= ERR_WARN;
4606 goto out;
4607 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004608
Willy Tarreau3842f002009-06-14 11:39:52 +02004609 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4610 curproxy->options2 &= ~cfg_opts2[optnum].val;
4611
4612 switch (kwm) {
4613 case KWM_STD:
4614 curproxy->options2 |= cfg_opts2[optnum].val;
4615 break;
4616 case KWM_NO:
4617 curproxy->no_options2 |= cfg_opts2[optnum].val;
4618 break;
4619 case KWM_DEF: /* already cleared */
4620 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004621 }
Willy Tarreau93893792009-07-23 13:19:11 +02004622 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004623 }
4624 }
4625
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004626 /* HTTP options override each other. They can be cancelled using
4627 * "no option xxx" which only switches to default mode if the mode
4628 * was this one (useful for cancelling options set in defaults
4629 * sections).
4630 */
4631 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004632 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4633 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004634 if (kwm == KWM_STD) {
4635 curproxy->options &= ~PR_O_HTTP_MODE;
4636 curproxy->options |= PR_O_HTTP_PCL;
4637 goto out;
4638 }
4639 else if (kwm == KWM_NO) {
4640 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4641 curproxy->options &= ~PR_O_HTTP_MODE;
4642 goto out;
4643 }
4644 }
4645 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004646 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4647 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004648 if (kwm == KWM_STD) {
4649 curproxy->options &= ~PR_O_HTTP_MODE;
4650 curproxy->options |= PR_O_HTTP_FCL;
4651 goto out;
4652 }
4653 else if (kwm == KWM_NO) {
4654 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4655 curproxy->options &= ~PR_O_HTTP_MODE;
4656 goto out;
4657 }
4658 }
4659 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004660 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4661 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004662 if (kwm == KWM_STD) {
4663 curproxy->options &= ~PR_O_HTTP_MODE;
4664 curproxy->options |= PR_O_HTTP_SCL;
4665 goto out;
4666 }
4667 else if (kwm == KWM_NO) {
4668 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4669 curproxy->options &= ~PR_O_HTTP_MODE;
4670 goto out;
4671 }
4672 }
4673 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004674 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4675 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004676 if (kwm == KWM_STD) {
4677 curproxy->options &= ~PR_O_HTTP_MODE;
4678 curproxy->options |= PR_O_HTTP_KAL;
4679 goto out;
4680 }
4681 else if (kwm == KWM_NO) {
4682 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4683 curproxy->options &= ~PR_O_HTTP_MODE;
4684 goto out;
4685 }
4686 }
4687 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004688 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4689 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004690 if (kwm == KWM_STD) {
4691 curproxy->options &= ~PR_O_HTTP_MODE;
4692 curproxy->options |= PR_O_HTTP_TUN;
4693 goto out;
4694 }
4695 else if (kwm == KWM_NO) {
4696 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4697 curproxy->options &= ~PR_O_HTTP_MODE;
4698 goto out;
4699 }
4700 }
4701
Joseph Lynch726ab712015-05-11 23:25:34 -07004702 /* Redispatch can take an integer argument that control when the
4703 * resispatch occurs. All values are relative to the retries option.
4704 * This can be cancelled using "no option xxx".
4705 */
4706 if (strcmp(args[1], "redispatch") == 0) {
4707 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4708 err_code |= ERR_WARN;
4709 goto out;
4710 }
4711
4712 curproxy->no_options &= ~PR_O_REDISP;
4713 curproxy->options &= ~PR_O_REDISP;
4714
4715 switch (kwm) {
4716 case KWM_STD:
4717 curproxy->options |= PR_O_REDISP;
4718 curproxy->redispatch_after = -1;
4719 if(*args[2]) {
4720 curproxy->redispatch_after = atol(args[2]);
4721 }
4722 break;
4723 case KWM_NO:
4724 curproxy->no_options |= PR_O_REDISP;
4725 curproxy->redispatch_after = 0;
4726 break;
4727 case KWM_DEF: /* already cleared */
4728 break;
4729 }
4730 goto out;
4731 }
4732
Willy Tarreau3842f002009-06-14 11:39:52 +02004733 if (kwm != KWM_STD) {
4734 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004735 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004736 err_code |= ERR_ALERT | ERR_FATAL;
4737 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004738 }
4739
Emeric Brun3a058f32009-06-30 18:26:00 +02004740 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004741 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004743 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004744 if (*(args[2]) != '\0') {
4745 if (!strcmp(args[2], "clf")) {
4746 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004747 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004748 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004749 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004752 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004753 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4754 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004755 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004756 if (curproxy->conf.logformat_string != default_http_log_format &&
4757 curproxy->conf.logformat_string != default_tcp_log_format &&
4758 curproxy->conf.logformat_string != clf_http_log_format)
4759 free(curproxy->conf.logformat_string);
4760 curproxy->conf.logformat_string = logformat;
4761
4762 free(curproxy->conf.lfs_file);
4763 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4764 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004765 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004766 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004768 if (curproxy->conf.logformat_string != default_http_log_format &&
4769 curproxy->conf.logformat_string != default_tcp_log_format &&
4770 curproxy->conf.logformat_string != clf_http_log_format)
4771 free(curproxy->conf.logformat_string);
4772 curproxy->conf.logformat_string = default_tcp_log_format;
4773
4774 free(curproxy->conf.lfs_file);
4775 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4776 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004777
4778 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4779 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004782 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004783 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004785
William Lallemanddf1425a2015-04-28 20:17:49 +02004786 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4787 goto out;
4788
Willy Tarreau13943ab2006-12-31 00:24:10 +01004789 if (curproxy->cap & PR_CAP_FE)
4790 curproxy->options |= PR_O_TCP_CLI_KA;
4791 if (curproxy->cap & PR_CAP_BE)
4792 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
4794 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004795 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_WARN;
4797
Willy Tarreaubaaee002006-06-26 02:48:02 +02004798 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004799 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004800 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004801 curproxy->options2 &= ~PR_O2_CHK_ANY;
4802 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 if (!*args[2]) { /* no argument */
4804 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4805 curproxy->check_len = strlen(DEF_CHECK_REQ);
4806 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004807 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004808 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004810 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004811 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004812 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 if (*args[4])
4814 reqlen += strlen(args[4]);
4815 else
4816 reqlen += strlen("HTTP/1.0");
4817
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004818 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004820 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004822 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4823 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004824 }
4825 else if (!strcmp(args[1], "ssl-hello-chk")) {
4826 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004828 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004829
Willy Tarreaua534fea2008-08-03 12:19:50 +02004830 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004831 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004832 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004833 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004834
4835 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 }
Willy Tarreau23677902007-05-08 23:50:35 +02004838 else if (!strcmp(args[1], "smtpchk")) {
4839 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004840 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004841 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004842 curproxy->options2 &= ~PR_O2_CHK_ANY;
4843 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004844
4845 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4846 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4847 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4848 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4849 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4850 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004851 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004852 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4853 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4854 } else {
4855 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4856 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4857 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4858 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4859 }
4860 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004861 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4862 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004863 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004864 else if (!strcmp(args[1], "pgsql-check")) {
4865 /* use PostgreSQL request to check servers' health */
4866 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4867 err_code |= ERR_WARN;
4868
4869 free(curproxy->check_req);
4870 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004871 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004872 curproxy->options2 |= PR_O2_PGSQL_CHK;
4873
4874 if (*(args[2])) {
4875 int cur_arg = 2;
4876
4877 while (*(args[cur_arg])) {
4878 if (strcmp(args[cur_arg], "user") == 0) {
4879 char * packet;
4880 uint32_t packet_len;
4881 uint32_t pv;
4882
4883 /* suboption header - needs additional argument for it */
4884 if (*(args[cur_arg+1]) == 0) {
4885 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4886 file, linenum, args[0], args[1], args[cur_arg]);
4887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
4889 }
4890
4891 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4892 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4893 pv = htonl(0x30000); /* protocol version 3.0 */
4894
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004895 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004896
4897 memcpy(packet + 4, &pv, 4);
4898
4899 /* copy "user" */
4900 memcpy(packet + 8, "user", 4);
4901
4902 /* copy username */
4903 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4904
4905 free(curproxy->check_req);
4906 curproxy->check_req = packet;
4907 curproxy->check_len = packet_len;
4908
4909 packet_len = htonl(packet_len);
4910 memcpy(packet, &packet_len, 4);
4911 cur_arg += 2;
4912 } else {
4913 /* unknown suboption - catchall */
4914 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4915 file, linenum, args[0], args[1]);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
4919 } /* end while loop */
4920 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004921 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4922 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004923 }
4924
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004925 else if (!strcmp(args[1], "redis-check")) {
4926 /* use REDIS PING request to check servers' health */
4927 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4928 err_code |= ERR_WARN;
4929
4930 free(curproxy->check_req);
4931 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004932 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004933 curproxy->options2 |= PR_O2_REDIS_CHK;
4934
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004935 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004936 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4937 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004938
4939 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4940 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004941 }
4942
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004943 else if (!strcmp(args[1], "mysql-check")) {
4944 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4946 err_code |= ERR_WARN;
4947
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004948 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004949 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004950 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004951 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004952
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004953 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004954 * const char mysql40_client_auth_pkt[] = {
4955 * "\x0e\x00\x00" // packet length
4956 * "\x01" // packet number
4957 * "\x00\x00" // client capabilities
4958 * "\x00\x00\x01" // max packet
4959 * "haproxy\x00" // username (null terminated string)
4960 * "\x00" // filler (always 0x00)
4961 * "\x01\x00\x00" // packet length
4962 * "\x00" // packet number
4963 * "\x01" // COM_QUIT command
4964 * };
4965 */
4966
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004967 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4968 * const char mysql41_client_auth_pkt[] = {
4969 * "\x0e\x00\x00\" // packet length
4970 * "\x01" // packet number
4971 * "\x00\x00\x00\x00" // client capabilities
4972 * "\x00\x00\x00\x01" // max packet
4973 * "\x21" // character set (UTF-8)
4974 * char[23] // All zeroes
4975 * "haproxy\x00" // username (null terminated string)
4976 * "\x00" // filler (always 0x00)
4977 * "\x01\x00\x00" // packet length
4978 * "\x00" // packet number
4979 * "\x01" // COM_QUIT command
4980 * };
4981 */
4982
4983
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004984 if (*(args[2])) {
4985 int cur_arg = 2;
4986
4987 while (*(args[cur_arg])) {
4988 if (strcmp(args[cur_arg], "user") == 0) {
4989 char *mysqluser;
4990 int packetlen, reqlen, userlen;
4991
4992 /* suboption header - needs additional argument for it */
4993 if (*(args[cur_arg+1]) == 0) {
4994 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4995 file, linenum, args[0], args[1], args[cur_arg]);
4996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
4998 }
4999 mysqluser = args[cur_arg + 1];
5000 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005001
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005002 if (*(args[cur_arg+2])) {
5003 if (!strcmp(args[cur_arg+2], "post-41")) {
5004 packetlen = userlen + 7 + 27;
5005 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005006
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005007 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005008 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005009 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005010
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005011 snprintf(curproxy->check_req, 4, "%c%c%c",
5012 ((unsigned char) packetlen & 0xff),
5013 ((unsigned char) (packetlen >> 8) & 0xff),
5014 ((unsigned char) (packetlen >> 16) & 0xff));
5015
5016 curproxy->check_req[3] = 1;
5017 curproxy->check_req[5] = 130;
5018 curproxy->check_req[11] = 1;
5019 curproxy->check_req[12] = 33;
5020 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5021 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5022 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5023 cur_arg += 3;
5024 } else {
5025 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
5028 }
5029 } else {
5030 packetlen = userlen + 7;
5031 reqlen = packetlen + 9;
5032
5033 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005034 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005035 curproxy->check_len = reqlen;
5036
5037 snprintf(curproxy->check_req, 4, "%c%c%c",
5038 ((unsigned char) packetlen & 0xff),
5039 ((unsigned char) (packetlen >> 8) & 0xff),
5040 ((unsigned char) (packetlen >> 16) & 0xff));
5041
5042 curproxy->check_req[3] = 1;
5043 curproxy->check_req[5] = 128;
5044 curproxy->check_req[8] = 1;
5045 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5046 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5047 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5048 cur_arg += 2;
5049 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005050 } else {
5051 /* unknown suboption - catchall */
5052 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5053 file, linenum, args[0], args[1]);
5054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
5056 }
5057 } /* end while loop */
5058 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005059 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005060 else if (!strcmp(args[1], "ldap-check")) {
5061 /* use LDAP request to check servers' health */
5062 free(curproxy->check_req);
5063 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005064 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005065 curproxy->options2 |= PR_O2_LDAP_CHK;
5066
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005067 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005068 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5069 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005070 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5071 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005072 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005073 else if (!strcmp(args[1], "tcp-check")) {
5074 /* use raw TCPCHK send/expect to check servers' health */
5075 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5076 err_code |= ERR_WARN;
5077
5078 free(curproxy->check_req);
5079 curproxy->check_req = NULL;
5080 curproxy->options2 &= ~PR_O2_CHK_ANY;
5081 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005082 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5083 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005084 }
Simon Horman98637e52014-06-20 12:30:16 +09005085 else if (!strcmp(args[1], "external-check")) {
5086 /* excute an external command to check servers' health */
5087 free(curproxy->check_req);
5088 curproxy->check_req = NULL;
5089 curproxy->options2 &= ~PR_O2_CHK_ANY;
5090 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005091 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5092 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005093 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005094 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005095 int cur_arg;
5096
5097 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5098 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005099 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005100
Willy Tarreau87cf5142011-08-19 22:57:24 +02005101 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005102
5103 free(curproxy->fwdfor_hdr_name);
5104 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5105 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5106
5107 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5108 cur_arg = 2;
5109 while (*(args[cur_arg])) {
5110 if (!strcmp(args[cur_arg], "except")) {
5111 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005112 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005113 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5114 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005117 }
5118 /* flush useless bits */
5119 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005120 cur_arg += 2;
5121 } else if (!strcmp(args[cur_arg], "header")) {
5122 /* suboption header - needs additional argument for it */
5123 if (*(args[cur_arg+1]) == 0) {
5124 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5125 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005128 }
5129 free(curproxy->fwdfor_hdr_name);
5130 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5131 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5132 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005133 } else if (!strcmp(args[cur_arg], "if-none")) {
5134 curproxy->options &= ~PR_O_FF_ALWAYS;
5135 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005136 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005137 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005138 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005139 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005142 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005143 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005144 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005145 else if (!strcmp(args[1], "originalto")) {
5146 int cur_arg;
5147
5148 /* insert x-original-to field, but not for the IP address listed as an except.
5149 * set default options (ie: bitfield, header name, etc)
5150 */
5151
5152 curproxy->options |= PR_O_ORGTO;
5153
5154 free(curproxy->orgto_hdr_name);
5155 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5156 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5157
Willy Tarreau87cf5142011-08-19 22:57:24 +02005158 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005159 cur_arg = 2;
5160 while (*(args[cur_arg])) {
5161 if (!strcmp(args[cur_arg], "except")) {
5162 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005163 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 +02005164 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5165 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005168 }
5169 /* flush useless bits */
5170 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5171 cur_arg += 2;
5172 } else if (!strcmp(args[cur_arg], "header")) {
5173 /* suboption header - needs additional argument for it */
5174 if (*(args[cur_arg+1]) == 0) {
5175 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5176 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005179 }
5180 free(curproxy->orgto_hdr_name);
5181 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5182 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5183 cur_arg += 2;
5184 } else {
5185 /* unknown suboption - catchall */
5186 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5187 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005190 }
5191 } /* end while loop */
5192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 else {
5194 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
Willy Tarreau93893792009-07-23 13:19:11 +02005198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005200 else if (!strcmp(args[0], "default_backend")) {
5201 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005203
5204 if (*(args[1]) == 0) {
5205 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005208 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005209 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005210 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005211
5212 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5213 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005216 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005217 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005218
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005219 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5220 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 +01005221 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005222 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 /* enable reconnections to dispatch */
5224 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005225
5226 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005229 else if (!strcmp(args[0], "http-reuse")) {
5230 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5231 err_code |= ERR_WARN;
5232
5233 if (strcmp(args[1], "never") == 0) {
5234 /* enable a graceful server shutdown on an HTTP 404 response */
5235 curproxy->options &= ~PR_O_REUSE_MASK;
5236 curproxy->options |= PR_O_REUSE_NEVR;
5237 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5238 goto out;
5239 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005240 else if (strcmp(args[1], "safe") == 0) {
5241 /* enable a graceful server shutdown on an HTTP 404 response */
5242 curproxy->options &= ~PR_O_REUSE_MASK;
5243 curproxy->options |= PR_O_REUSE_SAFE;
5244 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5245 goto out;
5246 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005247 else if (strcmp(args[1], "aggressive") == 0) {
5248 curproxy->options &= ~PR_O_REUSE_MASK;
5249 curproxy->options |= PR_O_REUSE_AGGR;
5250 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5251 goto out;
5252 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005253 else if (strcmp(args[1], "always") == 0) {
5254 /* enable a graceful server shutdown on an HTTP 404 response */
5255 curproxy->options &= ~PR_O_REUSE_MASK;
5256 curproxy->options |= PR_O_REUSE_ALWS;
5257 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5258 goto out;
5259 }
5260 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005261 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
5264 }
5265 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005266 else if (!strcmp(args[0], "http-check")) {
5267 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005268 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005269
5270 if (strcmp(args[1], "disable-on-404") == 0) {
5271 /* enable a graceful server shutdown on an HTTP 404 response */
5272 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005273 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5274 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005275 }
Willy Tarreauef781042010-01-27 11:53:01 +01005276 else if (strcmp(args[1], "send-state") == 0) {
5277 /* enable emission of the apparent state of a server in HTTP checks */
5278 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005279 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5280 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005281 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005282 else if (strcmp(args[1], "expect") == 0) {
5283 const char *ptr_arg;
5284 int cur_arg;
5285
5286 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5287 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5288 err_code |= ERR_ALERT | ERR_FATAL;
5289 goto out;
5290 }
5291
5292 cur_arg = 2;
5293 /* consider exclamation marks, sole or at the beginning of a word */
5294 while (*(ptr_arg = args[cur_arg])) {
5295 while (*ptr_arg == '!') {
5296 curproxy->options2 ^= PR_O2_EXP_INV;
5297 ptr_arg++;
5298 }
5299 if (*ptr_arg)
5300 break;
5301 cur_arg++;
5302 }
5303 /* now ptr_arg points to the beginning of a word past any possible
5304 * exclamation mark, and cur_arg is the argument which holds this word.
5305 */
5306 if (strcmp(ptr_arg, "status") == 0) {
5307 if (!*(args[cur_arg + 1])) {
5308 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5309 file, linenum, args[0], args[1], ptr_arg);
5310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005314 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005315 curproxy->expect_str = strdup(args[cur_arg + 1]);
5316 }
5317 else if (strcmp(ptr_arg, "string") == 0) {
5318 if (!*(args[cur_arg + 1])) {
5319 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5320 file, linenum, args[0], args[1], ptr_arg);
5321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
5323 }
5324 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005325 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005326 curproxy->expect_str = strdup(args[cur_arg + 1]);
5327 }
5328 else if (strcmp(ptr_arg, "rstatus") == 0) {
5329 if (!*(args[cur_arg + 1])) {
5330 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5331 file, linenum, args[0], args[1], ptr_arg);
5332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
5335 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005336 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005337 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005338 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005339 free(curproxy->expect_regex);
5340 curproxy->expect_regex = NULL;
5341 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005342 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005343 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5344 error = NULL;
5345 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5346 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5347 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5348 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
5352 }
5353 else if (strcmp(ptr_arg, "rstring") == 0) {
5354 if (!*(args[cur_arg + 1])) {
5355 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5356 file, linenum, args[0], args[1], ptr_arg);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005361 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005362 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005363 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005364 free(curproxy->expect_regex);
5365 curproxy->expect_regex = NULL;
5366 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005367 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005368 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5369 error = NULL;
5370 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5371 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5372 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5373 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
5377 }
5378 else {
5379 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5380 file, linenum, args[0], args[1], ptr_arg);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005385 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005386 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 +02005387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005389 }
5390 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005391 else if (!strcmp(args[0], "tcp-check")) {
5392 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5393 err_code |= ERR_WARN;
5394
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005395 if (strcmp(args[1], "comment") == 0) {
5396 int cur_arg;
5397 struct tcpcheck_rule *tcpcheck;
5398
5399 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005400 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005401 tcpcheck->action = TCPCHK_ACT_COMMENT;
5402
5403 if (!*args[cur_arg + 1]) {
5404 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5405 file, linenum, args[cur_arg]);
5406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
5409
5410 tcpcheck->comment = strdup(args[cur_arg + 1]);
5411
5412 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005413 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5414 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005415 }
5416 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005417 const char *ptr_arg;
5418 int cur_arg;
5419 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005420
5421 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005422 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5423 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5424 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5425 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5426 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005427
Willy Tarreau5581c272015-05-13 12:24:53 +02005428 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5429 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5430 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5431 file, linenum);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005434 }
5435
5436 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005437 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005438 tcpcheck->action = TCPCHK_ACT_CONNECT;
5439
5440 /* parsing each parameters to fill up the rule */
5441 while (*(ptr_arg = args[cur_arg])) {
5442 /* tcp port */
5443 if (strcmp(args[cur_arg], "port") == 0) {
5444 if ( (atol(args[cur_arg + 1]) > 65535) ||
5445 (atol(args[cur_arg + 1]) < 1) ){
5446 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5447 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
5451 tcpcheck->port = atol(args[cur_arg + 1]);
5452 cur_arg += 2;
5453 }
5454 /* send proxy protocol */
5455 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5456 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5457 cur_arg++;
5458 }
5459#ifdef USE_OPENSSL
5460 else if (strcmp(args[cur_arg], "ssl") == 0) {
5461 curproxy->options |= PR_O_TCPCHK_SSL;
5462 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5463 cur_arg++;
5464 }
5465#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005466 /* comment for this tcpcheck line */
5467 else if (strcmp(args[cur_arg], "comment") == 0) {
5468 if (!*args[cur_arg + 1]) {
5469 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5470 file, linenum, args[cur_arg]);
5471 err_code |= ERR_ALERT | ERR_FATAL;
5472 goto out;
5473 }
5474 tcpcheck->comment = strdup(args[cur_arg + 1]);
5475 cur_arg += 2;
5476 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005477 else {
5478#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005479 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 +01005480#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005481 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 +01005482#endif /* USE_OPENSSL */
5483 file, linenum, args[0], args[1], args[cur_arg]);
5484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
5486 }
5487
5488 }
5489
5490 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5491 }
5492 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005493 if (! *(args[2]) ) {
5494 /* SEND string expected */
5495 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5496 file, linenum, args[0], args[1], args[2]);
5497 err_code |= ERR_ALERT | ERR_FATAL;
5498 goto out;
5499 } else {
5500 struct tcpcheck_rule *tcpcheck;
5501
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005502 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005503
5504 tcpcheck->action = TCPCHK_ACT_SEND;
5505 tcpcheck->string_len = strlen(args[2]);
5506 tcpcheck->string = strdup(args[2]);
5507 tcpcheck->expect_regex = NULL;
5508
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005509 /* comment for this tcpcheck line */
5510 if (strcmp(args[3], "comment") == 0) {
5511 if (!*args[4]) {
5512 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5513 file, linenum, args[3]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 }
5517 tcpcheck->comment = strdup(args[4]);
5518 }
5519
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005520 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5521 }
5522 }
5523 else if (strcmp(args[1], "send-binary") == 0) {
5524 if (! *(args[2]) ) {
5525 /* SEND binary string expected */
5526 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5527 file, linenum, args[0], args[1], args[2]);
5528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
5530 } else {
5531 struct tcpcheck_rule *tcpcheck;
5532 char *err = NULL;
5533
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005534 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005535
5536 tcpcheck->action = TCPCHK_ACT_SEND;
5537 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5538 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5539 file, linenum, args[0], args[1], args[2], err);
5540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
5542 }
5543 tcpcheck->expect_regex = NULL;
5544
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005545 /* comment for this tcpcheck line */
5546 if (strcmp(args[3], "comment") == 0) {
5547 if (!*args[4]) {
5548 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5549 file, linenum, args[3]);
5550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
5552 }
5553 tcpcheck->comment = strdup(args[4]);
5554 }
5555
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005556 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5557 }
5558 }
5559 else if (strcmp(args[1], "expect") == 0) {
5560 const char *ptr_arg;
5561 int cur_arg;
5562 int inverse = 0;
5563
5564 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5565 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
5569
5570 cur_arg = 2;
5571 /* consider exclamation marks, sole or at the beginning of a word */
5572 while (*(ptr_arg = args[cur_arg])) {
5573 while (*ptr_arg == '!') {
5574 inverse = !inverse;
5575 ptr_arg++;
5576 }
5577 if (*ptr_arg)
5578 break;
5579 cur_arg++;
5580 }
5581 /* now ptr_arg points to the beginning of a word past any possible
5582 * exclamation mark, and cur_arg is the argument which holds this word.
5583 */
5584 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005585 struct tcpcheck_rule *tcpcheck;
5586 char *err = NULL;
5587
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005588 if (!*(args[cur_arg + 1])) {
5589 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5590 file, linenum, args[0], args[1], ptr_arg);
5591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
5593 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005594
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005595 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005596
5597 tcpcheck->action = TCPCHK_ACT_EXPECT;
5598 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5599 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5600 file, linenum, args[0], args[1], args[2], err);
5601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
5603 }
5604 tcpcheck->expect_regex = NULL;
5605 tcpcheck->inverse = inverse;
5606
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005607 /* tcpcheck comment */
5608 cur_arg += 2;
5609 if (strcmp(args[cur_arg], "comment") == 0) {
5610 if (!*args[cur_arg + 1]) {
5611 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5612 file, linenum, args[cur_arg + 1]);
5613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
5615 }
5616 tcpcheck->comment = strdup(args[cur_arg + 1]);
5617 }
5618
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005619 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5620 }
5621 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005622 struct tcpcheck_rule *tcpcheck;
5623
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005624 if (!*(args[cur_arg + 1])) {
5625 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5626 file, linenum, args[0], args[1], ptr_arg);
5627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
5629 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005630
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005631 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005632
5633 tcpcheck->action = TCPCHK_ACT_EXPECT;
5634 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5635 tcpcheck->string = strdup(args[cur_arg + 1]);
5636 tcpcheck->expect_regex = NULL;
5637 tcpcheck->inverse = inverse;
5638
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005639 /* tcpcheck comment */
5640 cur_arg += 2;
5641 if (strcmp(args[cur_arg], "comment") == 0) {
5642 if (!*args[cur_arg + 1]) {
5643 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5644 file, linenum, args[cur_arg + 1]);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
5648 tcpcheck->comment = strdup(args[cur_arg + 1]);
5649 }
5650
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005651 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5652 }
5653 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005654 struct tcpcheck_rule *tcpcheck;
5655
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005656 if (!*(args[cur_arg + 1])) {
5657 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5658 file, linenum, args[0], args[1], ptr_arg);
5659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
5661 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005662
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005663 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005664
5665 tcpcheck->action = TCPCHK_ACT_EXPECT;
5666 tcpcheck->string_len = 0;
5667 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005668 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5669 error = NULL;
5670 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5671 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5672 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5673 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
5676 }
5677 tcpcheck->inverse = inverse;
5678
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005679 /* tcpcheck comment */
5680 cur_arg += 2;
5681 if (strcmp(args[cur_arg], "comment") == 0) {
5682 if (!*args[cur_arg + 1]) {
5683 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5684 file, linenum, args[cur_arg + 1]);
5685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
5687 }
5688 tcpcheck->comment = strdup(args[cur_arg + 1]);
5689 }
5690
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005691 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5692 }
5693 else {
5694 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5695 file, linenum, args[0], args[1], ptr_arg);
5696 err_code |= ERR_ALERT | ERR_FATAL;
5697 goto out;
5698 }
5699 }
5700 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005701 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
5705 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005706 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005707 if (curproxy == &defproxy) {
5708 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005709 err_code |= ERR_ALERT | ERR_FATAL;
5710 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005711 }
5712
Willy Tarreaub80c2302007-11-30 20:51:32 +01005713 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005714 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005715
5716 if (strcmp(args[1], "fail") == 0) {
5717 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005718 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005719 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5720 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005723 }
5724
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005725 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5726 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5727 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005728 err_code |= ERR_ALERT | ERR_FATAL;
5729 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005730 }
5731 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5732 }
5733 else {
5734 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005737 }
5738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739#ifdef TPROXY
5740 else if (!strcmp(args[0], "transparent")) {
5741 /* enable transparent proxy connections */
5742 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005743 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 }
5746#endif
5747 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005748 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005749 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005750
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 if (*(args[1]) == 0) {
5752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 }
5756 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005757 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005760 else if (!strcmp(args[0], "backlog")) { /* backlog */
5761 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005763
5764 if (*(args[1]) == 0) {
5765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005768 }
5769 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005770 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5771 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005772 }
Willy Tarreau86034312006-12-29 00:10:33 +01005773 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005775 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005776
Willy Tarreau86034312006-12-29 00:10:33 +01005777 if (*(args[1]) == 0) {
5778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005779 err_code |= ERR_ALERT | ERR_FATAL;
5780 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005781 }
5782 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005783 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5784 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5787 if (*(args[1]) == 0) {
5788 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005792 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5793 if (err) {
5794 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5795 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005798 }
5799 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005800 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
5803 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005804 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005805 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005806 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005807
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 if (curproxy == &defproxy) {
5809 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005810 err_code |= ERR_ALERT | ERR_FATAL;
5811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005813 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005815
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005816 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005817 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005818 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005819 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005820 goto out;
5821 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005822
5823 proto = protocol_by_family(sk->ss_family);
5824 if (!proto || !proto->connect) {
5825 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5826 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
5829 }
5830
5831 if (port1 != port2) {
5832 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5833 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005834 err_code |= ERR_ALERT | ERR_FATAL;
5835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005837
5838 if (!port1) {
5839 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5840 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005841 err_code |= ERR_ALERT | ERR_FATAL;
5842 goto out;
5843 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005844
William Lallemanddf1425a2015-04-28 20:17:49 +02005845 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5846 goto out;
5847
Willy Tarreaud5191e72010-02-09 20:50:45 +01005848 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005849 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850 }
5851 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005853 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005854
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005855 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5856 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005861 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005862 /**
5863 * The syntax for hash-type config element is
5864 * hash-type {map-based|consistent} [[<algo>] avalanche]
5865 *
5866 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5867 */
5868 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005869
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005870 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5871 err_code |= ERR_WARN;
5872
5873 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005874 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5875 }
5876 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005877 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5878 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005879 else if (strcmp(args[1], "avalanche") == 0) {
5880 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]);
5881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005883 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005884 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005885 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005886 err_code |= ERR_ALERT | ERR_FATAL;
5887 goto out;
5888 }
Bhaskar98634f02013-10-29 23:30:51 -04005889
5890 /* set the hash function to use */
5891 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005892 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005893 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005894
5895 /* if consistent with no argument, then avalanche modifier is also applied */
5896 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5897 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005898 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005899 /* set the hash function */
5900 if (!strcmp(args[2], "sdbm")) {
5901 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5902 }
5903 else if (!strcmp(args[2], "djb2")) {
5904 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005905 }
5906 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005907 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005908 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005909 else if (!strcmp(args[2], "crc32")) {
5910 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5911 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005912 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005913 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 -05005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
5916 }
5917
5918 /* set the hash modifier */
5919 if (!strcmp(args[3], "avalanche")) {
5920 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5921 }
5922 else if (*args[3]) {
5923 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5924 err_code |= ERR_ALERT | ERR_FATAL;
5925 goto out;
5926 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005927 }
William Lallemanda73203e2012-03-12 12:48:57 +01005928 }
William Lallemanda73203e2012-03-12 12:48:57 +01005929 else if (strcmp(args[0], "unique-id-format") == 0) {
5930 if (!*(args[1])) {
5931 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5932 err_code |= ERR_ALERT | ERR_FATAL;
5933 goto out;
5934 }
William Lallemand3203ff42012-11-11 17:30:56 +01005935 if (*(args[2])) {
5936 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5937 err_code |= ERR_ALERT | ERR_FATAL;
5938 goto out;
5939 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005940 free(curproxy->conf.uniqueid_format_string);
5941 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005942
Willy Tarreau62a61232013-04-12 18:13:46 +02005943 free(curproxy->conf.uif_file);
5944 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5945 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005946 }
William Lallemanda73203e2012-03-12 12:48:57 +01005947
5948 else if (strcmp(args[0], "unique-id-header") == 0) {
5949 if (!*(args[1])) {
5950 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5951 err_code |= ERR_ALERT | ERR_FATAL;
5952 goto out;
5953 }
5954 free(curproxy->header_unique_id);
5955 curproxy->header_unique_id = strdup(args[1]);
5956 }
5957
William Lallemand723b73a2012-02-08 16:37:49 +01005958 else if (strcmp(args[0], "log-format") == 0) {
5959 if (!*(args[1])) {
5960 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5961 err_code |= ERR_ALERT | ERR_FATAL;
5962 goto out;
5963 }
William Lallemand3203ff42012-11-11 17:30:56 +01005964 if (*(args[2])) {
5965 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5966 err_code |= ERR_ALERT | ERR_FATAL;
5967 goto out;
5968 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005969
Willy Tarreau62a61232013-04-12 18:13:46 +02005970 if (curproxy->conf.logformat_string != default_http_log_format &&
5971 curproxy->conf.logformat_string != default_tcp_log_format &&
5972 curproxy->conf.logformat_string != clf_http_log_format)
5973 free(curproxy->conf.logformat_string);
5974 curproxy->conf.logformat_string = strdup(args[1]);
5975
5976 free(curproxy->conf.lfs_file);
5977 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5978 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005979
5980 /* get a chance to improve log-format error reporting by
5981 * reporting the correct line-number when possible.
5982 */
5983 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5984 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5985 file, linenum, curproxy->id);
5986 err_code |= ERR_WARN;
5987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005989 else if (!strcmp(args[0], "log-format-sd")) {
5990 if (!*(args[1])) {
5991 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5992 err_code |= ERR_ALERT | ERR_FATAL;
5993 goto out;
5994 }
5995 if (*(args[2])) {
5996 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
5999 }
6000
6001 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6002 free(curproxy->conf.logformat_sd_string);
6003 curproxy->conf.logformat_sd_string = strdup(args[1]);
6004
6005 free(curproxy->conf.lfsd_file);
6006 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6007 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6008
6009 /* get a chance to improve log-format-sd error reporting by
6010 * reporting the correct line-number when possible.
6011 */
6012 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6013 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6014 file, linenum, curproxy->id);
6015 err_code |= ERR_WARN;
6016 }
6017 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006018 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6019 if (*(args[1]) == 0) {
6020 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
6023 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006024 chunk_destroy(&curproxy->log_tag);
6025 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006026 }
William Lallemand0f99e342011-10-12 17:50:54 +02006027 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6028 /* delete previous herited or defined syslog servers */
6029 struct logsrv *back;
6030
6031 if (*(args[1]) != 0) {
6032 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6033 err_code |= ERR_ALERT | ERR_FATAL;
6034 goto out;
6035 }
6036
William Lallemand723b73a2012-02-08 16:37:49 +01006037 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6038 LIST_DEL(&tmplogsrv->list);
6039 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006040 }
6041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006042 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006043 struct logsrv *logsrv;
6044
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006046 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006047 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006048 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006049 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006050 LIST_INIT(&node->list);
6051 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 }
6054 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006055 struct sockaddr_storage *sk;
6056 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006057 int arg = 0;
6058 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006059
Vincent Bernat02779b62016-04-03 13:48:43 +02006060 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061
Willy Tarreau18324f52014-06-27 18:10:07 +02006062 /* just after the address, a length may be specified */
6063 if (strcmp(args[arg+2], "len") == 0) {
6064 len = atoi(args[arg+3]);
6065 if (len < 80 || len > 65535) {
6066 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6067 file, linenum, args[arg+3]);
6068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
6071 logsrv->maxlen = len;
6072
6073 /* skip these two args */
6074 arg += 2;
6075 }
6076 else
6077 logsrv->maxlen = MAX_SYSLOG_LEN;
6078
6079 if (logsrv->maxlen > global.max_syslog_len) {
6080 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02006081 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02006082 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006083 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006084 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006085 }
6086
Dragan Dosen1322d092015-09-22 16:05:32 +02006087 /* after the length, a format may be specified */
6088 if (strcmp(args[arg+2], "format") == 0) {
6089 logsrv->format = get_log_format(args[arg+3]);
6090 if (logsrv->format < 0) {
6091 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6092 err_code |= ERR_ALERT | ERR_FATAL;
6093 goto out;
6094 }
6095
6096 /* skip these two args */
6097 arg += 2;
6098 }
6099
William Lallemanddf1425a2015-04-28 20:17:49 +02006100 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6101 goto out;
6102
Willy Tarreau18324f52014-06-27 18:10:07 +02006103 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006104 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006105 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006106 err_code |= ERR_ALERT | ERR_FATAL;
6107 goto out;
6108
Willy Tarreaubaaee002006-06-26 02:48:02 +02006109 }
6110
William Lallemand0f99e342011-10-12 17:50:54 +02006111 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006112 if (*(args[arg+3])) {
6113 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006114 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006115 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006116 err_code |= ERR_ALERT | ERR_FATAL;
6117 goto out;
6118
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 }
6120 }
6121
William Lallemand0f99e342011-10-12 17:50:54 +02006122 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006123 if (*(args[arg+4])) {
6124 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006125 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006126 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006127 err_code |= ERR_ALERT | ERR_FATAL;
6128 goto out;
6129
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006130 }
6131 }
6132
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006133 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006134 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006135 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006136 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006137 goto out;
6138 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006139
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006140 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006141
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006142 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006143 if (port1 != port2) {
6144 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6145 file, linenum, args[0], args[1]);
6146 err_code |= ERR_ALERT | ERR_FATAL;
6147 goto out;
6148 }
6149
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006150 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006151 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 }
William Lallemand0f99e342011-10-12 17:50:54 +02006153
6154 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 }
6156 else {
6157 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6158 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006159 err_code |= ERR_ALERT | ERR_FATAL;
6160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 }
6162 }
6163 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006164 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006165 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006166 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006167 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006168
Willy Tarreau977b8e42006-12-29 14:19:17 +01006169 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006171
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006173 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6174 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006175 err_code |= ERR_ALERT | ERR_FATAL;
6176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006178
6179 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006180 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6181 free(curproxy->conn_src.iface_name);
6182 curproxy->conn_src.iface_name = NULL;
6183 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006184
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006185 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006186 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006187 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006188 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006189 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006190 goto out;
6191 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006192
6193 proto = protocol_by_family(sk->ss_family);
6194 if (!proto || !proto->connect) {
6195 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006196 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006197 err_code |= ERR_ALERT | ERR_FATAL;
6198 goto out;
6199 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006200
6201 if (port1 != port2) {
6202 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6203 file, linenum, args[0], args[1]);
6204 err_code |= ERR_ALERT | ERR_FATAL;
6205 goto out;
6206 }
6207
Willy Tarreauef9a3602012-12-08 22:29:20 +01006208 curproxy->conn_src.source_addr = *sk;
6209 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006210
6211 cur_arg = 2;
6212 while (*(args[cur_arg])) {
6213 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006214#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006215 if (!*args[cur_arg + 1]) {
6216 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6217 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006218 err_code |= ERR_ALERT | ERR_FATAL;
6219 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006220 }
6221
6222 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006223 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6224 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006225 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006226 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6227 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006228 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6229 char *name, *end;
6230
6231 name = args[cur_arg+1] + 7;
6232 while (isspace(*name))
6233 name++;
6234
6235 end = name;
6236 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6237 end++;
6238
Willy Tarreauef9a3602012-12-08 22:29:20 +01006239 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6240 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6241 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6242 curproxy->conn_src.bind_hdr_len = end - name;
6243 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6244 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6245 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006246
6247 /* now look for an occurrence number */
6248 while (isspace(*end))
6249 end++;
6250 if (*end == ',') {
6251 end++;
6252 name = end;
6253 if (*end == '-')
6254 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006255 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006256 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006257 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006258 }
6259
Willy Tarreauef9a3602012-12-08 22:29:20 +01006260 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006261 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6262 " occurrences values smaller than %d.\n",
6263 file, linenum, MAX_HDR_HISTORY);
6264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
6266 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006267 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006268 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006269
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006270 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006271 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006272 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006273 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006274 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006275 goto out;
6276 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006277
6278 proto = protocol_by_family(sk->ss_family);
6279 if (!proto || !proto->connect) {
6280 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6281 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006282 err_code |= ERR_ALERT | ERR_FATAL;
6283 goto out;
6284 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006285
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006286 if (port1 != port2) {
6287 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6288 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006289 err_code |= ERR_ALERT | ERR_FATAL;
6290 goto out;
6291 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006292 curproxy->conn_src.tproxy_addr = *sk;
6293 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006294 }
6295 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006296#else /* no TPROXY support */
6297 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006298 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006299 err_code |= ERR_ALERT | ERR_FATAL;
6300 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006301#endif
6302 cur_arg += 2;
6303 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006304 }
6305
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006306 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6307#ifdef SO_BINDTODEVICE
6308 if (!*args[cur_arg + 1]) {
6309 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006311 err_code |= ERR_ALERT | ERR_FATAL;
6312 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006313 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006314 free(curproxy->conn_src.iface_name);
6315 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6316 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006317 global.last_checks |= LSTCHK_NETADM;
6318#else
6319 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6320 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006321 err_code |= ERR_ALERT | ERR_FATAL;
6322 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006323#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006324 cur_arg += 2;
6325 continue;
6326 }
6327 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006328 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006329 err_code |= ERR_ALERT | ERR_FATAL;
6330 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006332 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006333 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6334 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6335 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006336 err_code |= ERR_ALERT | ERR_FATAL;
6337 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006340 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006341 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006343 err_code |= ERR_ALERT | ERR_FATAL;
6344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346
6347 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006348 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006349 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 }
6353 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006354 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006355 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006356 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 }
6360 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006362 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006363 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 }
6367 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006369 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006370 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 }
6374 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006376 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006377 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006381 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006383 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006384 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006386 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6391 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006392 err_code |= ERR_ALERT | ERR_FATAL;
6393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395
6396 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006397 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006398 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 }
6402 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006403 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006404 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006405 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 }
6409 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006410 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006411 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006412 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 }
6416 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006417 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006418 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006419 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006420 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 }
6423 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006425 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006426 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006430 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006432 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006433 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006434 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006435 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006438 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006439
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 if (curproxy == &defproxy) {
6441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006442 err_code |= ERR_ALERT | ERR_FATAL;
6443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006445 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006446 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 if (*(args[1]) == 0) {
6449 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006450 err_code |= ERR_ALERT | ERR_FATAL;
6451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006453
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006454 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006455 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6456 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6457 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006458 err_code |= ERR_ALERT | ERR_FATAL;
6459 goto out;
6460 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006461 err_code |= warnif_cond_conflicts(cond,
6462 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6463 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006464 }
6465 else if (*args[2]) {
6466 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6467 file, linenum, args[0], args[2]);
6468 err_code |= ERR_ALERT | ERR_FATAL;
6469 goto out;
6470 }
6471
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006472 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006473 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006474 wl->s = strdup(args[1]);
6475 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006476 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
6478 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6481 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006482 err_code |= ERR_ALERT | ERR_FATAL;
6483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006485
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006487 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006488 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 }
6492 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006494 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006495 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 }
6499 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006501 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006502 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 }
6506 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006510 err_code |= ERR_ALERT | ERR_FATAL;
6511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 }
6513
Willy Tarreauade5ec42010-01-28 19:33:49 +01006514 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006515 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006516 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006517 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 }
6520 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006521 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006522 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006523 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006524 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526 }
6527 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006528 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006529 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006530 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006531 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533 }
6534 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006535 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006536
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 if (curproxy == &defproxy) {
6538 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006539 err_code |= ERR_ALERT | ERR_FATAL;
6540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006542 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006543 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 if (*(args[1]) == 0) {
6546 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006547 err_code |= ERR_ALERT | ERR_FATAL;
6548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 }
6550
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006551 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006552 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6553 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6554 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006555 err_code |= ERR_ALERT | ERR_FATAL;
6556 goto out;
6557 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006558 err_code |= warnif_cond_conflicts(cond,
6559 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6560 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006561 }
6562 else if (*args[2]) {
6563 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6564 file, linenum, args[0], args[2]);
6565 err_code |= ERR_ALERT | ERR_FATAL;
6566 goto out;
6567 }
6568
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006569 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006570 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006571 wl->s = strdup(args[1]);
6572 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006573 }
6574 else if (!strcmp(args[0], "errorloc") ||
6575 !strcmp(args[0], "errorloc302") ||
6576 !strcmp(args[0], "errorloc303")) { /* error location */
6577 int errnum, errlen;
6578 char *err;
6579
Willy Tarreau977b8e42006-12-29 14:19:17 +01006580 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006581 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006582
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006584 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006585 err_code |= ERR_ALERT | ERR_FATAL;
6586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 }
6588
6589 errnum = atol(args[1]);
6590 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006591 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6592 err = malloc(errlen);
6593 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006595 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6596 err = malloc(errlen);
6597 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006598 }
6599
Willy Tarreau0f772532006-12-23 20:51:41 +01006600 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6601 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006602 chunk_destroy(&curproxy->errmsg[rc]);
6603 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006604 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006607
6608 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006609 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6610 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 free(err);
6612 }
6613 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006614 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6615 int errnum, errlen, fd;
6616 char *err;
6617 struct stat stat;
6618
6619 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006620 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006621
6622 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006623 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006624 err_code |= ERR_ALERT | ERR_FATAL;
6625 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006626 }
6627
6628 fd = open(args[2], O_RDONLY);
6629 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6630 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6631 file, linenum, args[2], args[1]);
6632 if (fd >= 0)
6633 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006634 err_code |= ERR_ALERT | ERR_FATAL;
6635 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006636 }
6637
Willy Tarreau27a674e2009-08-17 07:23:33 +02006638 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006639 errlen = stat.st_size;
6640 } else {
6641 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006642 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006643 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006644 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006645 }
6646
6647 err = malloc(errlen); /* malloc() must succeed during parsing */
6648 errnum = read(fd, err, errlen);
6649 if (errnum != errlen) {
6650 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6651 file, linenum, args[2], args[1]);
6652 close(fd);
6653 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006654 err_code |= ERR_ALERT | ERR_FATAL;
6655 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006656 }
6657 close(fd);
6658
6659 errnum = atol(args[1]);
6660 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6661 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006662 chunk_destroy(&curproxy->errmsg[rc]);
6663 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006664 break;
6665 }
6666 }
6667
6668 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006669 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6670 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006671 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006672 free(err);
6673 }
6674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006675 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006676 struct cfg_kw_list *kwl;
6677 int index;
6678
6679 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6680 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6681 if (kwl->kw[index].section != CFG_LISTEN)
6682 continue;
6683 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6684 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006685 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006686 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006687 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006688 err_code |= ERR_ALERT | ERR_FATAL;
6689 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006690 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006691 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006692 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006693 err_code |= ERR_WARN;
6694 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006695 }
Willy Tarreau93893792009-07-23 13:19:11 +02006696 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006697 }
6698 }
6699 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006700
Willy Tarreau6daf3432008-01-22 16:44:08 +01006701 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006702 err_code |= ERR_ALERT | ERR_FATAL;
6703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006704 }
Willy Tarreau93893792009-07-23 13:19:11 +02006705 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006706 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006707 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006708}
6709
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006710int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006711cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6712{
6713#ifdef CONFIG_HAP_NS
6714 const char *err;
6715 const char *item = args[0];
6716
6717 if (!strcmp(item, "namespace_list")) {
6718 return 0;
6719 }
6720 else if (!strcmp(item, "namespace")) {
6721 size_t idx = 1;
6722 const char *current;
6723 while (*(current = args[idx++])) {
6724 err = invalid_char(current);
6725 if (err) {
6726 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6727 file, linenum, *err, item, current);
6728 return ERR_ALERT | ERR_FATAL;
6729 }
6730
6731 if (netns_store_lookup(current, strlen(current))) {
6732 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6733 file, linenum, current);
6734 return ERR_ALERT | ERR_FATAL;
6735 }
6736 if (!netns_store_insert(current)) {
6737 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6738 file, linenum, current);
6739 return ERR_ALERT | ERR_FATAL;
6740 }
6741 }
6742 }
6743
6744 return 0;
6745#else
6746 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6747 file, linenum);
6748 return ERR_ALERT | ERR_FATAL;
6749#endif
6750}
6751
6752int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006753cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6754{
6755
6756 int err_code = 0;
6757 const char *err;
6758
6759 if (!strcmp(args[0], "userlist")) { /* new userlist */
6760 struct userlist *newul;
6761
6762 if (!*args[1]) {
6763 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6764 file, linenum, args[0]);
6765 err_code |= ERR_ALERT | ERR_FATAL;
6766 goto out;
6767 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006768 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6769 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006770
6771 err = invalid_char(args[1]);
6772 if (err) {
6773 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6774 file, linenum, *err, args[0], args[1]);
6775 err_code |= ERR_ALERT | ERR_FATAL;
6776 goto out;
6777 }
6778
6779 for (newul = userlist; newul; newul = newul->next)
6780 if (!strcmp(newul->name, args[1])) {
6781 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6782 file, linenum, args[1]);
6783 err_code |= ERR_WARN;
6784 goto out;
6785 }
6786
Vincent Bernat02779b62016-04-03 13:48:43 +02006787 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006788 if (!newul) {
6789 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6790 err_code |= ERR_ALERT | ERR_ABORT;
6791 goto out;
6792 }
6793
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006794 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006795 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006796 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6797 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006798 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006799 goto out;
6800 }
6801
6802 newul->next = userlist;
6803 userlist = newul;
6804
6805 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006806 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006807 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006808 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006809
6810 if (!*args[1]) {
6811 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6812 file, linenum, args[0]);
6813 err_code |= ERR_ALERT | ERR_FATAL;
6814 goto out;
6815 }
6816
6817 err = invalid_char(args[1]);
6818 if (err) {
6819 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6820 file, linenum, *err, args[0], args[1]);
6821 err_code |= ERR_ALERT | ERR_FATAL;
6822 goto out;
6823 }
6824
William Lallemand4ac9f542015-05-28 18:03:51 +02006825 if (!userlist)
6826 goto out;
6827
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006828 for (ag = userlist->groups; ag; ag = ag->next)
6829 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006830 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6831 file, linenum, args[1], userlist->name);
6832 err_code |= ERR_ALERT;
6833 goto out;
6834 }
6835
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006836 ag = calloc(1, sizeof(*ag));
6837 if (!ag) {
6838 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6839 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006840 goto out;
6841 }
6842
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006843 ag->name = strdup(args[1]);
6844 if (!ag) {
6845 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6846 err_code |= ERR_ALERT | ERR_ABORT;
6847 goto out;
6848 }
6849
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006850 cur_arg = 2;
6851
6852 while (*args[cur_arg]) {
6853 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006854 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006855 cur_arg += 2;
6856 continue;
6857 } else {
6858 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6859 file, linenum, args[0]);
6860 err_code |= ERR_ALERT | ERR_FATAL;
6861 goto out;
6862 }
6863 }
6864
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006865 ag->next = userlist->groups;
6866 userlist->groups = ag;
6867
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006868 } else if (!strcmp(args[0], "user")) { /* new user */
6869 struct auth_users *newuser;
6870 int cur_arg;
6871
6872 if (!*args[1]) {
6873 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6874 file, linenum, args[0]);
6875 err_code |= ERR_ALERT | ERR_FATAL;
6876 goto out;
6877 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006878 if (!userlist)
6879 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006880
6881 for (newuser = userlist->users; newuser; newuser = newuser->next)
6882 if (!strcmp(newuser->user, args[1])) {
6883 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6884 file, linenum, args[1], userlist->name);
6885 err_code |= ERR_ALERT;
6886 goto out;
6887 }
6888
Vincent Bernat02779b62016-04-03 13:48:43 +02006889 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006890 if (!newuser) {
6891 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6892 err_code |= ERR_ALERT | ERR_ABORT;
6893 goto out;
6894 }
6895
6896 newuser->user = strdup(args[1]);
6897
6898 newuser->next = userlist->users;
6899 userlist->users = newuser;
6900
6901 cur_arg = 2;
6902
6903 while (*args[cur_arg]) {
6904 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006905#ifdef CONFIG_HAP_CRYPT
6906 if (!crypt("", args[cur_arg + 1])) {
6907 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6908 file, linenum, newuser->user);
6909 err_code |= ERR_ALERT | ERR_FATAL;
6910 goto out;
6911 }
6912#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006913 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6914 file, linenum);
6915 err_code |= ERR_ALERT;
6916#endif
6917 newuser->pass = strdup(args[cur_arg + 1]);
6918 cur_arg += 2;
6919 continue;
6920 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6921 newuser->pass = strdup(args[cur_arg + 1]);
6922 newuser->flags |= AU_O_INSECURE;
6923 cur_arg += 2;
6924 continue;
6925 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006926 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006927 cur_arg += 2;
6928 continue;
6929 } else {
6930 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6931 file, linenum, args[0]);
6932 err_code |= ERR_ALERT | ERR_FATAL;
6933 goto out;
6934 }
6935 }
6936 } else {
6937 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6938 err_code |= ERR_ALERT | ERR_FATAL;
6939 }
6940
6941out:
6942 return err_code;
6943}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944
6945/*
6946 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006947 * Returns the error code, 0 if OK, or any combination of :
6948 * - ERR_ABORT: must abort ASAP
6949 * - ERR_FATAL: we can continue parsing but not start the service
6950 * - ERR_WARN: a warning has been emitted
6951 * - ERR_ALERT: an alert has been emitted
6952 * Only the two first ones can stop processing, the two others are just
6953 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006955int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006956{
William Lallemand64e84512015-05-12 14:25:37 +02006957 char *thisline;
6958 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006959 FILE *f;
6960 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006961 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006962 struct cfg_section *cs = NULL;
6963 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006964 int readbytes = 0;
6965
6966 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006967 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006968 return -1;
6969 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006970
6971 /* Register internal sections */
6972 if (!cfg_register_section("listen", cfg_parse_listen) ||
6973 !cfg_register_section("frontend", cfg_parse_listen) ||
6974 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006975 !cfg_register_section("defaults", cfg_parse_listen) ||
6976 !cfg_register_section("global", cfg_parse_global) ||
6977 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006978 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006979 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006980 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6981 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006982 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983
David Carlier97880bb2016-04-08 10:35:26 +01006984 if ((f=fopen(file,"r")) == NULL) {
6985 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006986 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006988
William Lallemandb2f07452015-05-12 14:27:13 +02006989next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006990 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006991 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006992 char *end;
6993 char *args[MAX_LINE_ARGS + 1];
6994 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006995 int dquote = 0; /* double quote */
6996 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006997
Willy Tarreaubaaee002006-06-26 02:48:02 +02006998 linenum++;
6999
7000 end = line + strlen(line);
7001
William Lallemand64e84512015-05-12 14:25:37 +02007002 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007003 /* Check if we reached the limit and the last char is not \n.
7004 * Watch out for the last line without the terminating '\n'!
7005 */
William Lallemand64e84512015-05-12 14:25:37 +02007006 char *newline;
7007 int newlinesize = linesize * 2;
7008
7009 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7010 if (newline == NULL) {
7011 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7012 file, linenum);
7013 err_code |= ERR_ALERT | ERR_FATAL;
7014 continue;
7015 }
7016
7017 readbytes = linesize - 1;
7018 linesize = newlinesize;
7019 thisline = newline;
7020 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007021 }
7022
William Lallemand64e84512015-05-12 14:25:37 +02007023 readbytes = 0;
7024
Willy Tarreaubaaee002006-06-26 02:48:02 +02007025 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007026 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007027 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007028
Willy Tarreaubaaee002006-06-26 02:48:02 +02007029 arg = 0;
7030 args[arg] = line;
7031
7032 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007033 if (*line == '"' && !squote) { /* double quote outside single quotes */
7034 if (dquote)
7035 dquote = 0;
7036 else
7037 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007038 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007039 end--;
7040 }
7041 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7042 if (squote)
7043 squote = 0;
7044 else
7045 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007046 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007047 end--;
7048 }
7049 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007050 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7051 * C equivalent value. Other combinations left unchanged (eg: \1).
7052 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007053 int skip = 0;
7054 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7055 *line = line[1];
7056 skip = 1;
7057 }
7058 else if (line[1] == 'r') {
7059 *line = '\r';
7060 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007062 else if (line[1] == 'n') {
7063 *line = '\n';
7064 skip = 1;
7065 }
7066 else if (line[1] == 't') {
7067 *line = '\t';
7068 skip = 1;
7069 }
7070 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007071 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007072 unsigned char hex1, hex2;
7073 hex1 = toupper(line[2]) - '0';
7074 hex2 = toupper(line[3]) - '0';
7075 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7076 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7077 *line = (hex1<<4) + hex2;
7078 skip = 3;
7079 }
7080 else {
7081 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007082 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007083 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007084 } else if (line[1] == '"') {
7085 *line = '"';
7086 skip = 1;
7087 } else if (line[1] == '\'') {
7088 *line = '\'';
7089 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007090 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7091 *line = '$';
7092 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 }
7094 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007095 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 end -= skip;
7097 }
7098 line++;
7099 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007100 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 /* end of string, end of loop */
7102 *line = 0;
7103 break;
7104 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007105 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007107 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007108 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109 line++;
7110 args[++arg] = line;
7111 }
William Lallemandb2f07452015-05-12 14:27:13 +02007112 else if (dquote && *line == '$') {
7113 /* environment variables are evaluated inside double quotes */
7114 char *var_beg;
7115 char *var_end;
7116 char save_char;
7117 char *value;
7118 int val_len;
7119 int newlinesize;
7120 int braces = 0;
7121
7122 var_beg = line + 1;
7123 var_end = var_beg;
7124
7125 if (*var_beg == '{') {
7126 var_beg++;
7127 var_end++;
7128 braces = 1;
7129 }
7130
7131 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7132 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7133 err_code |= ERR_ALERT | ERR_FATAL;
7134 goto next_line; /* skip current line */
7135 }
7136
7137 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7138 var_end++;
7139
7140 save_char = *var_end;
7141 *var_end = '\0';
7142 value = getenv(var_beg);
7143 *var_end = save_char;
7144 val_len = value ? strlen(value) : 0;
7145
7146 if (braces) {
7147 if (*var_end == '}') {
7148 var_end++;
7149 braces = 0;
7150 } else {
7151 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7152 err_code |= ERR_ALERT | ERR_FATAL;
7153 goto next_line; /* skip current line */
7154 }
7155 }
7156
7157 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7158
7159 /* if not enough space in thisline */
7160 if (newlinesize > linesize) {
7161 char *newline;
7162
7163 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7164 if (newline == NULL) {
7165 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7166 err_code |= ERR_ALERT | ERR_FATAL;
7167 goto next_line; /* slip current line */
7168 }
7169 /* recompute pointers if realloc returns a new pointer */
7170 if (newline != thisline) {
7171 int i;
7172 int diff;
7173
7174 for (i = 0; i <= arg; i++) {
7175 diff = args[i] - thisline;
7176 args[i] = newline + diff;
7177 }
7178
7179 diff = var_end - thisline;
7180 var_end = newline + diff;
7181 diff = end - thisline;
7182 end = newline + diff;
7183 diff = line - thisline;
7184 line = newline + diff;
7185 thisline = newline;
7186 }
7187 linesize = newlinesize;
7188 }
7189
7190 /* insert value inside the line */
7191 memmove(line + val_len, var_end, end - var_end + 1);
7192 memcpy(line, value, val_len);
7193 end += val_len - (var_end - line);
7194 line += val_len;
7195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007196 else {
7197 line++;
7198 }
7199 }
William Lallemandb2f07452015-05-12 14:27:13 +02007200
William Lallemandf9873ba2015-05-05 17:37:14 +02007201 if (dquote) {
7202 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7203 err_code |= ERR_ALERT | ERR_FATAL;
7204 }
7205
7206 if (squote) {
7207 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7208 err_code |= ERR_ALERT | ERR_FATAL;
7209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007210
7211 /* empty line */
7212 if (!**args)
7213 continue;
7214
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007215 if (*line) {
7216 /* we had to stop due to too many args.
7217 * Let's terminate the string, print the offending part then cut the
7218 * last arg.
7219 */
7220 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7221 line++;
7222 *line = '\0';
7223
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007224 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007225 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007226 err_code |= ERR_ALERT | ERR_FATAL;
7227 args[arg] = line;
7228 }
7229
Willy Tarreau540abe42007-05-02 20:50:16 +02007230 /* zero out remaining args and ensure that at least one entry
7231 * is zeroed out.
7232 */
7233 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007234 args[arg] = line;
7235 }
7236
Willy Tarreau3842f002009-06-14 11:39:52 +02007237 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007238 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007239 char *tmp;
7240
Willy Tarreau3842f002009-06-14 11:39:52 +02007241 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007242 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007243 for (arg=0; *args[arg+1]; arg++)
7244 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007245 *tmp = '\0'; // fix the next arg to \0
7246 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007247 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007248 else if (!strcmp(args[0], "default")) {
7249 kwm = KWM_DEF;
7250 for (arg=0; *args[arg+1]; arg++)
7251 args[arg] = args[arg+1]; // shift args after inversion
7252 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007253
William Lallemand0f99e342011-10-12 17:50:54 +02007254 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7255 strcmp(args[0], "log") != 0) {
7256 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007257 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007258 }
7259
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007260 /* detect section start */
7261 list_for_each_entry(ics, &sections, list) {
7262 if (strcmp(args[0], ics->section_name) == 0) {
7263 cursection = ics->section_name;
7264 cs = ics;
7265 break;
7266 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007267 }
7268
Willy Tarreaubaaee002006-06-26 02:48:02 +02007269 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007270 if (cs)
7271 err_code |= cs->section_parser(file, linenum, args, kwm);
7272 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007273 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007274 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007275 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007276
7277 if (err_code & ERR_ABORT)
7278 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007279 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007280 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007281 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007282 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007283 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007284}
7285
Willy Tarreau64ab6072014-09-16 12:17:36 +02007286/* This function propagates processes from frontend <from> to backend <to> so
7287 * that it is always guaranteed that a backend pointed to by a frontend is
7288 * bound to all of its processes. After that, if the target is a "listen"
7289 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007290 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007291 * checked first to ensure that <to> is already bound to all processes of
7292 * <from>, there is no risk of looping and we ensure to follow the shortest
7293 * path to the destination.
7294 *
7295 * It is possible to set <to> to NULL for the first call so that the function
7296 * takes care of visiting the initial frontend in <from>.
7297 *
7298 * It is important to note that the function relies on the fact that all names
7299 * have already been resolved.
7300 */
7301void propagate_processes(struct proxy *from, struct proxy *to)
7302{
7303 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007304
7305 if (to) {
7306 /* check whether we need to go down */
7307 if (from->bind_proc &&
7308 (from->bind_proc & to->bind_proc) == from->bind_proc)
7309 return;
7310
7311 if (!from->bind_proc && !to->bind_proc)
7312 return;
7313
7314 to->bind_proc = from->bind_proc ?
7315 (to->bind_proc | from->bind_proc) : 0;
7316
7317 /* now propagate down */
7318 from = to;
7319 }
7320
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007321 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007322 return;
7323
Willy Tarreauf6b70012014-12-18 14:00:43 +01007324 if (from->state == PR_STSTOPPED)
7325 return;
7326
Willy Tarreau64ab6072014-09-16 12:17:36 +02007327 /* default_backend */
7328 if (from->defbe.be)
7329 propagate_processes(from, from->defbe.be);
7330
7331 /* use_backend */
7332 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007333 if (rule->dynamic)
7334 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007335 to = rule->be.backend;
7336 propagate_processes(from, to);
7337 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007338}
7339
Willy Tarreaubb925012009-07-23 13:36:36 +02007340/*
7341 * Returns the error code, 0 if OK, or any combination of :
7342 * - ERR_ABORT: must abort ASAP
7343 * - ERR_FATAL: we can continue parsing but not start the service
7344 * - ERR_WARN: a warning has been emitted
7345 * - ERR_ALERT: an alert has been emitted
7346 * Only the two first ones can stop processing, the two others are just
7347 * indicators.
7348 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007349int check_config_validity()
7350{
7351 int cfgerr = 0;
7352 struct proxy *curproxy = NULL;
7353 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007354 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007355 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007356 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007357
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007358 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007359 /*
7360 * Now, check for the integrity of all that we have collected.
7361 */
7362
7363 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007364 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007365
Willy Tarreau193b8c62012-11-22 00:17:38 +01007366 if (!global.tune.max_http_hdr)
7367 global.tune.max_http_hdr = MAX_HTTP_HDR;
7368
7369 if (!global.tune.cookie_len)
7370 global.tune.cookie_len = CAPTURE_LEN;
7371
7372 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7373
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007374 /* Post initialisation of the users and groups lists. */
7375 err_code = userlist_postinit();
7376 if (err_code != ERR_NONE)
7377 goto out;
7378
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007379 /* first, we will invert the proxy list order */
7380 curproxy = NULL;
7381 while (proxy) {
7382 struct proxy *next;
7383
7384 next = proxy->next;
7385 proxy->next = curproxy;
7386 curproxy = proxy;
7387 if (!next)
7388 break;
7389 proxy = next;
7390 }
7391
Willy Tarreau419ead82014-09-16 13:41:21 +02007392 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007393 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007394 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007395 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007396 struct act_rule *trule;
7397 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007398 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007399 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007400 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007401
Willy Tarreau050536d2012-10-04 08:47:34 +02007402 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007403 /* proxy ID not set, use automatic numbering with first
7404 * spare entry starting with next_pxid.
7405 */
7406 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7407 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7408 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007409 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007410 next_pxid++;
7411
Willy Tarreau55ea7572007-06-17 19:56:27 +02007412
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007414 /* ensure we don't keep listeners uselessly bound */
7415 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007416 free((void *)curproxy->table.peers.name);
7417 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007418 continue;
7419 }
7420
Willy Tarreau102df612014-05-07 23:56:38 +02007421 /* Check multi-process mode compatibility for the current proxy */
7422
7423 if (curproxy->bind_proc) {
7424 /* an explicit bind-process was specified, let's check how many
7425 * processes remain.
7426 */
David Carliere6c39412015-07-02 07:00:17 +00007427 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007428
7429 curproxy->bind_proc &= nbits(global.nbproc);
7430 if (!curproxy->bind_proc && nbproc == 1) {
7431 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);
7432 curproxy->bind_proc = 1;
7433 }
7434 else if (!curproxy->bind_proc && nbproc > 1) {
7435 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);
7436 curproxy->bind_proc = 0;
7437 }
7438 }
7439
Willy Tarreau3d209582014-05-09 17:06:11 +02007440 /* check and reduce the bind-proc of each listener */
7441 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7442 unsigned long mask;
7443
7444 if (!bind_conf->bind_proc)
7445 continue;
7446
7447 mask = nbits(global.nbproc);
7448 if (curproxy->bind_proc)
7449 mask &= curproxy->bind_proc;
7450 /* mask cannot be null here thanks to the previous checks */
7451
David Carliere6c39412015-07-02 07:00:17 +00007452 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007453 bind_conf->bind_proc &= mask;
7454
7455 if (!bind_conf->bind_proc && nbproc == 1) {
7456 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",
7457 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7458 bind_conf->bind_proc = mask & ~(mask - 1);
7459 }
7460 else if (!bind_conf->bind_proc && nbproc > 1) {
7461 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",
7462 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7463 bind_conf->bind_proc = 0;
7464 }
7465 }
7466
Willy Tarreauff01a212009-03-15 13:46:16 +01007467 switch (curproxy->mode) {
7468 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007469 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007470 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007471 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7472 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007473 cfgerr++;
7474 }
7475
7476 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007477 Warning("config : servers will be ignored for %s '%s'.\n",
7478 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007479 break;
7480
7481 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007482 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007483 break;
7484
7485 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007486 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007487 break;
7488 }
7489
Willy Tarreauf3934b82015-08-11 11:36:45 +02007490 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7491 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7492 proxy_type_str(curproxy), curproxy->id);
7493 err_code |= ERR_WARN;
7494 }
7495
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007496 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007497 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007498 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007499 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7500 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007501 cfgerr++;
7502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007503#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007504 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007505 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7506 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007507 cfgerr++;
7508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007509#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007510 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007511 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7512 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007513 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007514 }
7515 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007516 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007517 /* If no LB algo is set in a backend, and we're not in
7518 * transparent mode, dispatch mode nor proxy mode, we
7519 * want to use balance roundrobin by default.
7520 */
7521 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7522 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007523 }
7524 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007525
Willy Tarreau1620ec32011-08-06 17:05:02 +02007526 if (curproxy->options & PR_O_DISPATCH)
7527 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7528 else if (curproxy->options & PR_O_HTTP_PROXY)
7529 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7530 else if (curproxy->options & PR_O_TRANSP)
7531 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007532
Willy Tarreau1620ec32011-08-06 17:05:02 +02007533 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7534 if (curproxy->options & PR_O_DISABLE404) {
7535 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7536 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7537 err_code |= ERR_WARN;
7538 curproxy->options &= ~PR_O_DISABLE404;
7539 }
7540 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7541 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7542 "send-state", proxy_type_str(curproxy), curproxy->id);
7543 err_code |= ERR_WARN;
7544 curproxy->options &= ~PR_O2_CHK_SNDST;
7545 }
Willy Tarreauef781042010-01-27 11:53:01 +01007546 }
7547
Simon Horman98637e52014-06-20 12:30:16 +09007548 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7549 if (!global.external_check) {
7550 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7551 curproxy->id, "option external-check");
7552 cfgerr++;
7553 }
7554 if (!curproxy->check_command) {
7555 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7556 curproxy->id, "option external-check");
7557 cfgerr++;
7558 }
7559 }
7560
Simon Horman64e34162015-02-06 11:11:57 +09007561 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007562 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7563 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007564 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7565 "'email-alert myhostname', or 'email-alert to' "
7566 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007567 "to be present).\n",
7568 proxy_type_str(curproxy), curproxy->id);
7569 err_code |= ERR_WARN;
7570 free_email_alert(curproxy);
7571 }
7572 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007573 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007574 }
7575
Simon Horman98637e52014-06-20 12:30:16 +09007576 if (curproxy->check_command) {
7577 int clear = 0;
7578 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7579 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7580 "external-check command", proxy_type_str(curproxy), curproxy->id);
7581 err_code |= ERR_WARN;
7582 clear = 1;
7583 }
7584 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007585 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007586 curproxy->id, "external-check command");
7587 cfgerr++;
7588 }
7589 if (clear) {
7590 free(curproxy->check_command);
7591 curproxy->check_command = NULL;
7592 }
7593 }
7594
7595 if (curproxy->check_path) {
7596 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7597 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7598 "external-check path", proxy_type_str(curproxy), curproxy->id);
7599 err_code |= ERR_WARN;
7600 free(curproxy->check_path);
7601 curproxy->check_path = NULL;
7602 }
7603 }
7604
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007605 /* if a default backend was specified, let's find it */
7606 if (curproxy->defbe.name) {
7607 struct proxy *target;
7608
Willy Tarreauafb39922015-05-26 12:04:09 +02007609 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007610 if (!target) {
7611 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7612 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007613 cfgerr++;
7614 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007615 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7616 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007617 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007618 } else if (target->mode != curproxy->mode &&
7619 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7620
7621 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7622 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7623 curproxy->conf.file, curproxy->conf.line,
7624 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7625 target->conf.file, target->conf.line);
7626 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007627 } else {
7628 free(curproxy->defbe.name);
7629 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007630
7631 /* Emit a warning if this proxy also has some servers */
7632 if (curproxy->srv) {
7633 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7634 curproxy->id);
7635 err_code |= ERR_WARN;
7636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007637 }
7638 }
7639
Willy Tarreau55ea7572007-06-17 19:56:27 +02007640 /* find the target proxy for 'use_backend' rules */
7641 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007642 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007643 struct logformat_node *node;
7644 char *pxname;
7645
7646 /* Try to parse the string as a log format expression. If the result
7647 * of the parsing is only one entry containing a simple string, then
7648 * it's a standard string corresponding to a static rule, thus the
7649 * parsing is cancelled and be.name is restored to be resolved.
7650 */
7651 pxname = rule->be.name;
7652 LIST_INIT(&rule->be.expr);
7653 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7654 curproxy->conf.args.file, curproxy->conf.args.line);
7655 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7656
7657 if (!LIST_ISEMPTY(&rule->be.expr)) {
7658 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7659 rule->dynamic = 1;
7660 free(pxname);
7661 continue;
7662 }
7663 /* simple string: free the expression and fall back to static rule */
7664 free(node->arg);
7665 free(node);
7666 }
7667
7668 rule->dynamic = 0;
7669 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007670
Willy Tarreauafb39922015-05-26 12:04:09 +02007671 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007672 if (!target) {
7673 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7674 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007675 cfgerr++;
7676 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007677 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7678 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007679 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007680 } else if (target->mode != curproxy->mode &&
7681 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7682
7683 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7684 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7685 curproxy->conf.file, curproxy->conf.line,
7686 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7687 target->conf.file, target->conf.line);
7688 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007689 } else {
7690 free((void *)rule->be.name);
7691 rule->be.backend = target;
7692 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007693 }
7694
Willy Tarreau64ab6072014-09-16 12:17:36 +02007695 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007696 list_for_each_entry(srule, &curproxy->server_rules, list) {
7697 struct server *target = findserver(curproxy, srule->srv.name);
7698
7699 if (!target) {
7700 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7701 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7702 cfgerr++;
7703 continue;
7704 }
7705 free((void *)srule->srv.name);
7706 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007707 }
7708
Emeric Brunb982a3d2010-01-04 15:45:53 +01007709 /* find the target table for 'stick' rules */
7710 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7711 struct proxy *target;
7712
Emeric Brun1d33b292010-01-04 15:47:17 +01007713 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7714 if (mrule->flags & STK_IS_STORE)
7715 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7716
Emeric Brunb982a3d2010-01-04 15:45:53 +01007717 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007718 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007719 else
7720 target = curproxy;
7721
7722 if (!target) {
7723 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7724 curproxy->id, mrule->table.name);
7725 cfgerr++;
7726 }
7727 else if (target->table.size == 0) {
7728 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7729 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7730 cfgerr++;
7731 }
Willy Tarreau12785782012-04-27 21:37:17 +02007732 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7733 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007734 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7735 cfgerr++;
7736 }
7737 else {
7738 free((void *)mrule->table.name);
7739 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007740 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007741 }
7742 }
7743
7744 /* find the target table for 'store response' rules */
7745 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7746 struct proxy *target;
7747
Emeric Brun1d33b292010-01-04 15:47:17 +01007748 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7749
Emeric Brunb982a3d2010-01-04 15:45:53 +01007750 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007751 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007752 else
7753 target = curproxy;
7754
7755 if (!target) {
7756 Alert("Proxy '%s': unable to find store table '%s'.\n",
7757 curproxy->id, mrule->table.name);
7758 cfgerr++;
7759 }
7760 else if (target->table.size == 0) {
7761 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7762 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7763 cfgerr++;
7764 }
Willy Tarreau12785782012-04-27 21:37:17 +02007765 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7766 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007767 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7768 cfgerr++;
7769 }
7770 else {
7771 free((void *)mrule->table.name);
7772 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007773 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007774 }
7775 }
7776
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007777 /* find the target table for 'tcp-request' layer 4 rules */
7778 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7779 struct proxy *target;
7780
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007781 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007782 continue;
7783
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007784 if (trule->arg.trk_ctr.table.n)
7785 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007786 else
7787 target = curproxy;
7788
7789 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007790 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007791 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007792 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007793 cfgerr++;
7794 }
7795 else if (target->table.size == 0) {
7796 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007797 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007798 cfgerr++;
7799 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007800 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007801 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007802 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007803 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007804 cfgerr++;
7805 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007806 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007807 free(trule->arg.trk_ctr.table.n);
7808 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007809 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007810 * to pass a list of counters to track and allocate them right here using
7811 * stktable_alloc_data_type().
7812 */
7813 }
7814 }
7815
Willy Tarreaud1f96522010-08-03 19:34:32 +02007816 /* find the target table for 'tcp-request' layer 6 rules */
7817 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7818 struct proxy *target;
7819
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007820 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007821 continue;
7822
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007823 if (trule->arg.trk_ctr.table.n)
7824 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007825 else
7826 target = curproxy;
7827
7828 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007829 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007830 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007831 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007832 cfgerr++;
7833 }
7834 else if (target->table.size == 0) {
7835 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007836 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007837 cfgerr++;
7838 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007839 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007840 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007841 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007842 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007843 cfgerr++;
7844 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007845 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007846 free(trule->arg.trk_ctr.table.n);
7847 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007848 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007849 * to pass a list of counters to track and allocate them right here using
7850 * stktable_alloc_data_type().
7851 */
7852 }
7853 }
7854
Baptiste Assmanne9544932015-11-03 23:31:35 +01007855 /* parse http-request capture rules to ensure id really exists */
7856 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7857 if (hrqrule->action != ACT_CUSTOM ||
7858 hrqrule->action_ptr != http_action_req_capture_by_id)
7859 continue;
7860
7861 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7862 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7863 curproxy->id, hrqrule->arg.capid.idx);
7864 cfgerr++;
7865 }
7866 }
7867
7868 /* parse http-response capture rules to ensure id really exists */
7869 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7870 if (hrqrule->action != ACT_CUSTOM ||
7871 hrqrule->action_ptr != http_action_res_capture_by_id)
7872 continue;
7873
7874 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7875 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7876 curproxy->id, hrqrule->arg.capid.idx);
7877 cfgerr++;
7878 }
7879 }
7880
Willy Tarreau09448f72014-06-25 18:12:15 +02007881 /* find the target table for 'http-request' layer 7 rules */
7882 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7883 struct proxy *target;
7884
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007885 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007886 continue;
7887
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007888 if (hrqrule->arg.trk_ctr.table.n)
7889 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007890 else
7891 target = curproxy;
7892
7893 if (!target) {
7894 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007895 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007896 http_req_trk_idx(hrqrule->action));
7897 cfgerr++;
7898 }
7899 else if (target->table.size == 0) {
7900 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007901 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007902 cfgerr++;
7903 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007904 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007905 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007906 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007907 http_req_trk_idx(hrqrule->action));
7908 cfgerr++;
7909 }
7910 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007911 free(hrqrule->arg.trk_ctr.table.n);
7912 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007913 /* Note: if we decide to enhance the track-sc syntax, we may be able
7914 * to pass a list of counters to track and allocate them right here using
7915 * stktable_alloc_data_type().
7916 */
7917 }
7918 }
7919
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007920 /* move any "block" rules at the beginning of the http-request rules */
7921 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7922 /* insert block_rules into http_req_rules at the beginning */
7923 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7924 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7925 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7926 curproxy->http_req_rules.n = curproxy->block_rules.n;
7927 LIST_INIT(&curproxy->block_rules);
7928 }
7929
Emeric Brun32da3c42010-09-23 18:39:19 +02007930 if (curproxy->table.peers.name) {
7931 struct peers *curpeers = peers;
7932
7933 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7934 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7935 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007936 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007937 break;
7938 }
7939 }
7940
7941 if (!curpeers) {
7942 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7943 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007944 free((void *)curproxy->table.peers.name);
7945 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007946 cfgerr++;
7947 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007948 else if (curpeers->state == PR_STSTOPPED) {
7949 /* silently disable this peers section */
7950 curproxy->table.peers.p = NULL;
7951 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007952 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007953 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7954 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007955 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007956 cfgerr++;
7957 }
7958 }
7959
Simon Horman9dc49962015-01-30 11:22:59 +09007960
7961 if (curproxy->email_alert.mailers.name) {
7962 struct mailers *curmailers = mailers;
7963
7964 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7965 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7966 free(curproxy->email_alert.mailers.name);
7967 curproxy->email_alert.mailers.m = curmailers;
7968 curmailers->users++;
7969 break;
7970 }
7971 }
7972
7973 if (!curmailers) {
7974 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7975 curproxy->id, curproxy->email_alert.mailers.name);
7976 free_email_alert(curproxy);
7977 cfgerr++;
7978 }
7979 }
7980
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007981 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007982 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007983 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7984 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7985 "proxy", curproxy->id);
7986 cfgerr++;
7987 goto out_uri_auth_compat;
7988 }
7989
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007990 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007991 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007992 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007993 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007994
Willy Tarreau95fa4692010-02-01 13:05:50 +01007995 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7996 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007997
7998 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007999 uri_auth_compat_req[i++] = "realm";
8000 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8001 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008002
Willy Tarreau95fa4692010-02-01 13:05:50 +01008003 uri_auth_compat_req[i++] = "unless";
8004 uri_auth_compat_req[i++] = "{";
8005 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8006 uri_auth_compat_req[i++] = "}";
8007 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008008
Willy Tarreauff011f22011-01-06 17:51:27 +01008009 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8010 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008011 cfgerr++;
8012 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008013 }
8014
Willy Tarreauff011f22011-01-06 17:51:27 +01008015 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008016
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008017 if (curproxy->uri_auth->auth_realm) {
8018 free(curproxy->uri_auth->auth_realm);
8019 curproxy->uri_auth->auth_realm = NULL;
8020 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008021
8022 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008023 }
8024out_uri_auth_compat:
8025
Dragan Dosen43885c72015-10-01 13:18:13 +02008026 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008027 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008028 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8029 if (!curproxy->conf.logformat_sd_string) {
8030 /* set the default logformat_sd_string */
8031 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8032 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008033 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008034 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008035 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008036
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008037 /* compile the log format */
8038 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008039 if (curproxy->conf.logformat_string != default_http_log_format &&
8040 curproxy->conf.logformat_string != default_tcp_log_format &&
8041 curproxy->conf.logformat_string != clf_http_log_format)
8042 free(curproxy->conf.logformat_string);
8043 curproxy->conf.logformat_string = NULL;
8044 free(curproxy->conf.lfs_file);
8045 curproxy->conf.lfs_file = NULL;
8046 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008047
8048 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8049 free(curproxy->conf.logformat_sd_string);
8050 curproxy->conf.logformat_sd_string = NULL;
8051 free(curproxy->conf.lfsd_file);
8052 curproxy->conf.lfsd_file = NULL;
8053 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008054 }
8055
Willy Tarreau62a61232013-04-12 18:13:46 +02008056 if (curproxy->conf.logformat_string) {
8057 curproxy->conf.args.ctx = ARGC_LOG;
8058 curproxy->conf.args.file = curproxy->conf.lfs_file;
8059 curproxy->conf.args.line = curproxy->conf.lfs_line;
8060 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008061 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008062 curproxy->conf.args.file = NULL;
8063 curproxy->conf.args.line = 0;
8064 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008065
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008066 if (curproxy->conf.logformat_sd_string) {
8067 curproxy->conf.args.ctx = ARGC_LOGSD;
8068 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8069 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8070 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8071 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8072 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8073 curproxy->conf.args.file = NULL;
8074 curproxy->conf.args.line = 0;
8075 }
8076
Willy Tarreau62a61232013-04-12 18:13:46 +02008077 if (curproxy->conf.uniqueid_format_string) {
8078 curproxy->conf.args.ctx = ARGC_UIF;
8079 curproxy->conf.args.file = curproxy->conf.uif_file;
8080 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008081 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008082 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008083 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008084 curproxy->conf.args.file = NULL;
8085 curproxy->conf.args.line = 0;
8086 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008087
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008088 /* only now we can check if some args remain unresolved.
8089 * This must be done after the users and groups resolution.
8090 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008091 cfgerr += smp_resolve_args(curproxy);
8092 if (!cfgerr)
8093 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008094
Willy Tarreau2738a142006-07-08 17:28:09 +02008095 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008096 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008097 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008098 (!curproxy->timeout.connect ||
8099 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008100 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008101 " | While not properly invalid, you will certainly encounter various problems\n"
8102 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008103 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008104 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008105 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008106 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008107
Willy Tarreau1fa31262007-12-03 00:36:16 +01008108 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8109 * We must still support older configurations, so let's find out whether those
8110 * parameters have been set or must be copied from contimeouts.
8111 */
8112 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008113 if (!curproxy->timeout.tarpit ||
8114 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008115 /* tarpit timeout not set. We search in the following order:
8116 * default.tarpit, curr.connect, default.connect.
8117 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008118 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008119 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008120 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008121 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008122 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008123 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008124 }
8125 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008126 (!curproxy->timeout.queue ||
8127 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008128 /* queue timeout not set. We search in the following order:
8129 * default.queue, curr.connect, default.connect.
8130 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008131 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008132 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008133 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008134 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008135 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008136 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008137 }
8138 }
8139
Willy Tarreau1620ec32011-08-06 17:05:02 +02008140 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008141 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008142 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008143 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008144 }
8145
Willy Tarreau215663d2014-06-13 18:30:23 +02008146 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8147 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8148 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8149 proxy_type_str(curproxy), curproxy->id);
8150 err_code |= ERR_WARN;
8151 }
8152
Willy Tarreau193b8c62012-11-22 00:17:38 +01008153 /* ensure that cookie capture length is not too large */
8154 if (curproxy->capture_len >= global.tune.cookie_len) {
8155 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8156 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8157 err_code |= ERR_WARN;
8158 curproxy->capture_len = global.tune.cookie_len - 1;
8159 }
8160
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008161 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008162 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008163 curproxy->req_cap_pool = create_pool("ptrcap",
8164 curproxy->nb_req_cap * sizeof(char *),
8165 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008166 }
8167
8168 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008169 curproxy->rsp_cap_pool = create_pool("ptrcap",
8170 curproxy->nb_rsp_cap * sizeof(char *),
8171 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008172 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008173
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008174 switch (curproxy->load_server_state_from_file) {
8175 case PR_SRV_STATE_FILE_UNSPEC:
8176 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8177 break;
8178 case PR_SRV_STATE_FILE_GLOBAL:
8179 if (!global.server_state_file) {
8180 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",
8181 curproxy->id);
8182 err_code |= ERR_WARN;
8183 }
8184 break;
8185 }
8186
Willy Tarreaubaaee002006-06-26 02:48:02 +02008187 /* first, we will invert the servers list order */
8188 newsrv = NULL;
8189 while (curproxy->srv) {
8190 struct server *next;
8191
8192 next = curproxy->srv->next;
8193 curproxy->srv->next = newsrv;
8194 newsrv = curproxy->srv;
8195 if (!next)
8196 break;
8197 curproxy->srv = next;
8198 }
8199
Willy Tarreau17edc812014-01-03 12:14:34 +01008200 /* Check that no server name conflicts. This causes trouble in the stats.
8201 * We only emit a warning for the first conflict affecting each server,
8202 * in order to avoid combinatory explosion if all servers have the same
8203 * name. We do that only for servers which do not have an explicit ID,
8204 * because these IDs were made also for distinguishing them and we don't
8205 * want to annoy people who correctly manage them.
8206 */
8207 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8208 struct server *other_srv;
8209
8210 if (newsrv->puid)
8211 continue;
8212
8213 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8214 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8215 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8216 newsrv->conf.file, newsrv->conf.line,
8217 proxy_type_str(curproxy), curproxy->id,
8218 newsrv->id, other_srv->conf.line);
8219 break;
8220 }
8221 }
8222 }
8223
Willy Tarreaudd701652010-05-25 23:03:02 +02008224 /* assign automatic UIDs to servers which don't have one yet */
8225 next_id = 1;
8226 newsrv = curproxy->srv;
8227 while (newsrv != NULL) {
8228 if (!newsrv->puid) {
8229 /* server ID not set, use automatic numbering with first
8230 * spare entry starting with next_svid.
8231 */
8232 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8233 newsrv->conf.id.key = newsrv->puid = next_id;
8234 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8235 }
8236 next_id++;
8237 newsrv = newsrv->next;
8238 }
8239
Willy Tarreau20697042007-11-15 23:26:18 +01008240 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008241 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008242
Willy Tarreau62c3be22012-01-20 13:12:32 +01008243 /*
8244 * If this server supports a maxconn parameter, it needs a dedicated
8245 * tasks to fill the emptied slots when a connection leaves.
8246 * Also, resolve deferred tracking dependency if needed.
8247 */
8248 newsrv = curproxy->srv;
8249 while (newsrv != NULL) {
8250 if (newsrv->minconn > newsrv->maxconn) {
8251 /* Only 'minconn' was specified, or it was higher than or equal
8252 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8253 * this will avoid further useless expensive computations.
8254 */
8255 newsrv->maxconn = newsrv->minconn;
8256 } else if (newsrv->maxconn && !newsrv->minconn) {
8257 /* minconn was not specified, so we set it to maxconn */
8258 newsrv->minconn = newsrv->maxconn;
8259 }
8260
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008261#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008262 if (newsrv->use_ssl || newsrv->check.use_ssl)
8263 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008264#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008265
Willy Tarreau2f075e92013-12-03 11:11:34 +01008266 /* set the check type on the server */
8267 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8268
Willy Tarreau62c3be22012-01-20 13:12:32 +01008269 if (newsrv->trackit) {
8270 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008271 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008272 char *pname, *sname;
8273
8274 pname = newsrv->trackit;
8275 sname = strrchr(pname, '/');
8276
8277 if (sname)
8278 *sname++ = '\0';
8279 else {
8280 sname = pname;
8281 pname = NULL;
8282 }
8283
8284 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008285 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008286 if (!px) {
8287 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8288 proxy_type_str(curproxy), curproxy->id,
8289 newsrv->id, pname);
8290 cfgerr++;
8291 goto next_srv;
8292 }
8293 } else
8294 px = curproxy;
8295
8296 srv = findserver(px, sname);
8297 if (!srv) {
8298 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8299 proxy_type_str(curproxy), curproxy->id,
8300 newsrv->id, sname);
8301 cfgerr++;
8302 goto next_srv;
8303 }
8304
Willy Tarreau32091232014-05-16 13:52:00 +02008305 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8306 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8307 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008308 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008309 "tracking as it does not have any check nor agent enabled.\n",
8310 proxy_type_str(curproxy), curproxy->id,
8311 newsrv->id, px->id, srv->id);
8312 cfgerr++;
8313 goto next_srv;
8314 }
8315
8316 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8317
8318 if (loop) {
8319 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8320 "belongs to a tracking chain looping back to %s/%s.\n",
8321 proxy_type_str(curproxy), curproxy->id,
8322 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008323 cfgerr++;
8324 goto next_srv;
8325 }
8326
8327 if (curproxy != px &&
8328 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8329 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8330 "tracking: disable-on-404 option inconsistency.\n",
8331 proxy_type_str(curproxy), curproxy->id,
8332 newsrv->id, px->id, srv->id);
8333 cfgerr++;
8334 goto next_srv;
8335 }
8336
8337 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008338 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008339 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008340 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008341 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008342 }
8343
8344 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008345 newsrv->tracknext = srv->trackers;
8346 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008347
8348 free(newsrv->trackit);
8349 newsrv->trackit = NULL;
8350 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008351
8352 /*
8353 * resolve server's resolvers name and update the resolvers pointer
8354 * accordingly
8355 */
8356 if (newsrv->resolvers_id) {
8357 struct dns_resolvers *curr_resolvers;
8358 int found;
8359
8360 found = 0;
8361 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8362 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8363 found = 1;
8364 break;
8365 }
8366 }
8367
8368 if (!found) {
8369 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8370 proxy_type_str(curproxy), curproxy->id,
8371 newsrv->id, newsrv->resolvers_id);
8372 cfgerr++;
8373 } else {
8374 free(newsrv->resolvers_id);
8375 newsrv->resolvers_id = NULL;
8376 if (newsrv->resolution)
8377 newsrv->resolution->resolvers = curr_resolvers;
8378 }
8379 }
8380 else {
8381 /* if no resolvers section associated to this server
8382 * we can clean up the associated resolution structure
8383 */
8384 if (newsrv->resolution) {
8385 free(newsrv->resolution->hostname_dn);
8386 newsrv->resolution->hostname_dn = NULL;
8387 free(newsrv->resolution);
8388 newsrv->resolution = NULL;
8389 }
8390 }
8391
Willy Tarreau62c3be22012-01-20 13:12:32 +01008392 next_srv:
8393 newsrv = newsrv->next;
8394 }
8395
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008396 /* We have to initialize the server lookup mechanism depending
8397 * on what LB algorithm was choosen.
8398 */
8399
8400 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8401 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8402 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008403 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8404 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8405 init_server_map(curproxy);
8406 } else {
8407 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8408 fwrr_init_server_groups(curproxy);
8409 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008410 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008411
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008412 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008413 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8414 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8415 fwlc_init_server_tree(curproxy);
8416 } else {
8417 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8418 fas_init_server_tree(curproxy);
8419 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008420 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008421
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008422 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008423 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8424 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8425 chash_init_server_tree(curproxy);
8426 } else {
8427 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8428 init_server_map(curproxy);
8429 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008430 break;
8431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008432
8433 if (curproxy->options & PR_O_LOGASAP)
8434 curproxy->to_log &= ~LW_BYTES;
8435
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008436 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008437 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8438 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008439 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8440 proxy_type_str(curproxy), curproxy->id);
8441 err_code |= ERR_WARN;
8442 }
8443
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008444 if (curproxy->mode != PR_MODE_HTTP) {
8445 int optnum;
8446
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008447 if (curproxy->uri_auth) {
8448 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8449 proxy_type_str(curproxy), curproxy->id);
8450 err_code |= ERR_WARN;
8451 curproxy->uri_auth = NULL;
8452 }
8453
Willy Tarreau87cf5142011-08-19 22:57:24 +02008454 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008455 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8456 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8457 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008458 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008459 }
8460
8461 if (curproxy->options & PR_O_ORGTO) {
8462 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8463 "originalto", proxy_type_str(curproxy), curproxy->id);
8464 err_code |= ERR_WARN;
8465 curproxy->options &= ~PR_O_ORGTO;
8466 }
8467
8468 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8469 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8470 (curproxy->cap & cfg_opts[optnum].cap) &&
8471 (curproxy->options & cfg_opts[optnum].val)) {
8472 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8473 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8474 err_code |= ERR_WARN;
8475 curproxy->options &= ~cfg_opts[optnum].val;
8476 }
8477 }
8478
8479 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8480 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8481 (curproxy->cap & cfg_opts2[optnum].cap) &&
8482 (curproxy->options2 & cfg_opts2[optnum].val)) {
8483 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8484 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8485 err_code |= ERR_WARN;
8486 curproxy->options2 &= ~cfg_opts2[optnum].val;
8487 }
8488 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008489
Willy Tarreau29fbe512015-08-20 19:35:14 +02008490#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008491 if (curproxy->conn_src.bind_hdr_occ) {
8492 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008493 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008494 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008495 err_code |= ERR_WARN;
8496 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008497#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008498 }
8499
Willy Tarreaubaaee002006-06-26 02:48:02 +02008500 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008501 * ensure that we're not cross-dressing a TCP server into HTTP.
8502 */
8503 newsrv = curproxy->srv;
8504 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008505 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008506 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8507 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008508 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008509 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008510
Willy Tarreau0cec3312011-10-31 13:49:26 +01008511 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8512 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8513 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8514 err_code |= ERR_WARN;
8515 }
8516
Willy Tarreauc93cd162014-05-13 15:54:22 +02008517 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008518 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8519 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8520 err_code |= ERR_WARN;
8521 }
8522
Willy Tarreau29fbe512015-08-20 19:35:14 +02008523#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008524 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8525 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008526 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 +01008527 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008528 err_code |= ERR_WARN;
8529 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008530#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008531 newsrv = newsrv->next;
8532 }
8533
Willy Tarreaue42bd962014-09-16 16:21:19 +02008534 /* check if we have a frontend with "tcp-request content" looking at L7
8535 * with no inspect-delay
8536 */
8537 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8538 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008539 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008540 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008541 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008542 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008543 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008544 break;
8545 }
8546
8547 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8548 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8549 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8550 " This means that these rules will randomly find their contents. This can be fixed by"
8551 " setting the tcp-request inspect-delay.\n",
8552 proxy_type_str(curproxy), curproxy->id);
8553 err_code |= ERR_WARN;
8554 }
8555 }
8556
Christopher Fauletd7c91962015-04-30 11:48:27 +02008557 /* Check filter configuration, if any */
8558 cfgerr += flt_check(curproxy);
8559
Willy Tarreauc1a21672009-08-16 22:37:44 +02008560 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008561 if (!curproxy->accept)
8562 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008563
Willy Tarreauc1a21672009-08-16 22:37:44 +02008564 if (curproxy->tcp_req.inspect_delay ||
8565 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008566 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008567
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008568 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008569 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008570 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008571 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008572
8573 /* both TCP and HTTP must check switching rules */
8574 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008575
8576 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008577 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008578 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8579 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008580 if (curproxy->mode == PR_MODE_HTTP) {
8581 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8582 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8583 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008584 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008585 }
8586
8587 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008588 if (curproxy->tcp_req.inspect_delay ||
8589 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8590 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8591
Emeric Brun97679e72010-09-23 17:56:44 +02008592 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8593 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8594
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008595 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008596 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008597 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008598 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008599
8600 /* If the backend does requires RDP cookie persistence, we have to
8601 * enable the corresponding analyser.
8602 */
8603 if (curproxy->options2 & PR_O2_RDPC_PRST)
8604 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008605
8606 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008607 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008608 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8609 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008610 if (curproxy->mode == PR_MODE_HTTP) {
8611 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8612 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8613 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008614 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008615 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008616 }
8617
8618 /***********************************************************/
8619 /* At this point, target names have already been resolved. */
8620 /***********************************************************/
8621
8622 /* Check multi-process mode compatibility */
8623
8624 if (global.nbproc > 1 && global.stats_fe) {
8625 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8626 unsigned long mask;
8627
8628 mask = nbits(global.nbproc);
8629 if (global.stats_fe->bind_proc)
8630 mask &= global.stats_fe->bind_proc;
8631
8632 if (bind_conf->bind_proc)
8633 mask &= bind_conf->bind_proc;
8634
8635 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008636 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008637 break;
8638 }
8639 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8640 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");
8641 }
8642 }
8643
8644 /* Make each frontend inherit bind-process from its listeners when not specified. */
8645 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8646 if (curproxy->bind_proc)
8647 continue;
8648
8649 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8650 unsigned long mask;
8651
Willy Tarreaue428b082015-05-04 21:57:58 +02008652 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008653 curproxy->bind_proc |= mask;
8654 }
8655
8656 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008657 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008658 }
8659
8660 if (global.stats_fe) {
8661 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8662 unsigned long mask;
8663
Cyril Bonté06181952016-02-24 00:14:54 +01008664 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008665 global.stats_fe->bind_proc |= mask;
8666 }
8667 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008668 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008669 }
8670
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008671 /* propagate bindings from frontends to backends. Don't do it if there
8672 * are any fatal errors as we must not call it with unresolved proxies.
8673 */
8674 if (!cfgerr) {
8675 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8676 if (curproxy->cap & PR_CAP_FE)
8677 propagate_processes(curproxy, NULL);
8678 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008679 }
8680
8681 /* Bind each unbound backend to all processes when not specified. */
8682 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8683 if (curproxy->bind_proc)
8684 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008685 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008686 }
8687
8688 /*******************************************************/
8689 /* At this step, all proxies have a non-null bind_proc */
8690 /*******************************************************/
8691
8692 /* perform the final checks before creating tasks */
8693
8694 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8695 struct listener *listener;
8696 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008697
Emeric Brunc52962f2012-11-15 18:28:02 +01008698#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008699 /* Configure SSL for each bind line.
8700 * Note: if configuration fails at some point, the ->ctx member
8701 * remains NULL so that listeners can later detach.
8702 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008703 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008704 int alloc_ctx;
8705
Emeric Brunc52962f2012-11-15 18:28:02 +01008706 if (!bind_conf->is_ssl) {
8707 if (bind_conf->default_ctx) {
8708 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8709 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8710 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008711 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008712 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008713 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008714 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008715 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008716 cfgerr++;
8717 continue;
8718 }
8719
Emeric Brun8dc60392014-05-09 13:52:00 +02008720 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008721 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008722 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8723 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");
8724 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008725 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008726 cfgerr++;
8727 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008728 }
8729
Emeric Brunfc0421f2012-09-07 17:30:07 +02008730 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008731 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008732
8733 /* initialize CA variables if the certificates generation is enabled */
8734 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008735 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008736#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008737
Willy Tarreaue6b98942007-10-29 01:09:36 +01008738 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008739 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008740 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008741 int nbproc;
8742
8743 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008744 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008745 nbits(global.nbproc));
8746
8747 if (!nbproc) /* no intersection between listener and frontend */
8748 nbproc = 1;
8749
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008750 if (!listener->luid) {
8751 /* listener ID not set, use automatic numbering with first
8752 * spare entry starting with next_luid.
8753 */
8754 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8755 listener->conf.id.key = listener->luid = next_id;
8756 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008757 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008758 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008759
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008760 /* enable separate counters */
8761 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008762 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008763 if (!listener->name)
8764 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008765 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008766
Willy Tarreaue6b98942007-10-29 01:09:36 +01008767 if (curproxy->options & PR_O_TCP_NOLING)
8768 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008769 if (!listener->maxconn)
8770 listener->maxconn = curproxy->maxconn;
8771 if (!listener->backlog)
8772 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008773 if (!listener->maxaccept)
8774 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8775
8776 /* we want to have an optimal behaviour on single process mode to
8777 * maximize the work at once, but in multi-process we want to keep
8778 * some fairness between processes, so we target half of the max
8779 * number of events to be balanced over all the processes the proxy
8780 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8781 * used to disable the limit.
8782 */
8783 if (listener->maxaccept > 0) {
8784 if (nbproc > 1)
8785 listener->maxaccept = (listener->maxaccept + 1) / 2;
8786 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8787 }
8788
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008789 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008790 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008791 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008792 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008793
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008794 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8795 listener->options |= LI_O_TCP_RULES;
8796
Willy Tarreaude3041d2010-05-31 10:56:17 +02008797 if (curproxy->mon_mask.s_addr)
8798 listener->options |= LI_O_CHK_MONNET;
8799
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008800 /* smart accept mode is automatic in HTTP mode */
8801 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008802 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008803 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8804 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008805 }
8806
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008807 /* Release unused SSL configs */
8808 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8809 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008810 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008811#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008812 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008813 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008814 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008815 free(bind_conf->ca_sign_file);
8816 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008817 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008818 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008819 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008820 if(bind_conf->keys_ref) {
8821 free(bind_conf->keys_ref->filename);
8822 free(bind_conf->keys_ref->tlskeys);
8823 free(bind_conf->keys_ref);
8824 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008825#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008826 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008827
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008828 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008829 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008830 int count, maxproc = 0;
8831
8832 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008833 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008834 if (count > maxproc)
8835 maxproc = count;
8836 }
8837 /* backends have 0, frontends have 1 or more */
8838 if (maxproc != 1)
8839 Warning("Proxy '%s': in multi-process mode, stats will be"
8840 " limited to process assigned to the current request.\n",
8841 curproxy->id);
8842
Willy Tarreau102df612014-05-07 23:56:38 +02008843 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8844 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8845 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008846 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008847 }
Willy Tarreau102df612014-05-07 23:56:38 +02008848 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8849 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8850 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008851 }
8852 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008853
8854 /* create the task associated with the proxy */
8855 curproxy->task = task_new();
8856 if (curproxy->task) {
8857 curproxy->task->context = curproxy;
8858 curproxy->task->process = manage_proxy;
8859 /* no need to queue, it will be done automatically if some
8860 * listener gets limited.
8861 */
8862 curproxy->task->expire = TICK_ETERNITY;
8863 } else {
8864 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8865 curproxy->id);
8866 cfgerr++;
8867 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008868 }
8869
Willy Tarreaufbb78422011-06-05 15:38:35 +02008870 /* automatically compute fullconn if not set. We must not do it in the
8871 * loop above because cross-references are not yet fully resolved.
8872 */
8873 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8874 /* If <fullconn> is not set, let's set it to 10% of the sum of
8875 * the possible incoming frontend's maxconns.
8876 */
8877 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8878 struct proxy *fe;
8879 int total = 0;
8880
8881 /* sum up the number of maxconns of frontends which
8882 * reference this backend at least once or which are
8883 * the same one ('listen').
8884 */
8885 for (fe = proxy; fe; fe = fe->next) {
8886 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008887 int found = 0;
8888
8889 if (!(fe->cap & PR_CAP_FE))
8890 continue;
8891
8892 if (fe == curproxy) /* we're on a "listen" instance */
8893 found = 1;
8894
8895 if (fe->defbe.be == curproxy) /* "default_backend" */
8896 found = 1;
8897
8898 /* check if a "use_backend" rule matches */
8899 if (!found) {
8900 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008901 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008902 found = 1;
8903 break;
8904 }
8905 }
8906 }
8907
Willy Tarreaufbb78422011-06-05 15:38:35 +02008908 /* now we've checked all possible ways to reference a backend
8909 * from a frontend.
8910 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008911 if (!found)
8912 continue;
8913 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008914 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008915 /* we have the sum of the maxconns in <total>. We only
8916 * keep 10% of that sum to set the default fullconn, with
8917 * a hard minimum of 1 (to avoid a divide by zero).
8918 */
8919 curproxy->fullconn = (total + 9) / 10;
8920 if (!curproxy->fullconn)
8921 curproxy->fullconn = 1;
8922 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008923 }
8924
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008925 /*
8926 * Recount currently required checks.
8927 */
8928
8929 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8930 int optnum;
8931
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008932 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8933 if (curproxy->options & cfg_opts[optnum].val)
8934 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008935
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008936 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8937 if (curproxy->options2 & cfg_opts2[optnum].val)
8938 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008939 }
8940
Willy Tarreau0fca4832015-05-01 19:12:05 +02008941 /* compute the required process bindings for the peers */
8942 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8943 if (curproxy->table.peers.p)
8944 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8945
Willy Tarreau122541c2011-09-07 21:24:49 +02008946 if (peers) {
8947 struct peers *curpeers = peers, **last;
8948 struct peer *p, *pb;
8949
Willy Tarreau1e273012015-05-01 19:15:17 +02008950 /* Remove all peers sections which don't have a valid listener,
8951 * which are not used by any table, or which are bound to more
8952 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008953 */
8954 last = &peers;
8955 while (*last) {
8956 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008957
8958 if (curpeers->state == PR_STSTOPPED) {
8959 /* the "disabled" keyword was present */
8960 if (curpeers->peers_fe)
8961 stop_proxy(curpeers->peers_fe);
8962 curpeers->peers_fe = NULL;
8963 }
8964 else if (!curpeers->peers_fe) {
8965 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8966 curpeers->id, localpeer);
8967 }
David Carliere6c39412015-07-02 07:00:17 +00008968 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008969 /* either it's totally stopped or too much used */
8970 if (curpeers->peers_fe->bind_proc) {
8971 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008972 "running in different processes (%d different ones). "
8973 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008974 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008975 cfgerr++;
8976 }
8977 stop_proxy(curpeers->peers_fe);
8978 curpeers->peers_fe = NULL;
8979 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008980 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008981 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008982 last = &curpeers->next;
8983 continue;
8984 }
8985
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008986 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008987 p = curpeers->remote;
8988 while (p) {
8989 pb = p->next;
8990 free(p->id);
8991 free(p);
8992 p = pb;
8993 }
8994
8995 /* Destroy and unlink this curpeers section.
8996 * Note: curpeers is backed up into *last.
8997 */
8998 free(curpeers->id);
8999 curpeers = curpeers->next;
9000 free(*last);
9001 *last = curpeers;
9002 }
9003 }
9004
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009005 /* initialize stick-tables on backend capable proxies. This must not
9006 * be done earlier because the data size may be discovered while parsing
9007 * other proxies.
9008 */
9009 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9010 if (curproxy->state == PR_STSTOPPED)
9011 continue;
9012
9013 if (!stktable_init(&curproxy->table)) {
9014 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9015 cfgerr++;
9016 }
9017 }
9018
Simon Horman0d16a402015-01-30 11:22:58 +09009019 if (mailers) {
9020 struct mailers *curmailers = mailers, **last;
9021 struct mailer *m, *mb;
9022
9023 /* Remove all mailers sections which don't have a valid listener.
9024 * This can happen when a mailers section is never referenced.
9025 */
9026 last = &mailers;
9027 while (*last) {
9028 curmailers = *last;
9029 if (curmailers->users) {
9030 last = &curmailers->next;
9031 continue;
9032 }
9033
9034 Warning("Removing incomplete section 'mailers %s'.\n",
9035 curmailers->id);
9036
9037 m = curmailers->mailer_list;
9038 while (m) {
9039 mb = m->next;
9040 free(m->id);
9041 free(m);
9042 m = mb;
9043 }
9044
9045 /* Destroy and unlink this curmailers section.
9046 * Note: curmailers is backed up into *last.
9047 */
9048 free(curmailers->id);
9049 curmailers = curmailers->next;
9050 free(*last);
9051 *last = curmailers;
9052 }
9053 }
9054
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009055 /* Update server_state_file_name to backend name if backend is supposed to use
9056 * a server-state file locally defined and none has been provided */
9057 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9058 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9059 curproxy->server_state_file_name == NULL)
9060 curproxy->server_state_file_name = strdup(curproxy->id);
9061 }
9062
Willy Tarreau34eb6712011-10-24 18:15:04 +02009063 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009064 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009065 MEM_F_SHARED);
9066
Willy Tarreaubb925012009-07-23 13:36:36 +02009067 if (cfgerr > 0)
9068 err_code |= ERR_ALERT | ERR_FATAL;
9069 out:
9070 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009071}
9072
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009073/*
9074 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9075 * parsing sessions.
9076 */
9077void cfg_register_keywords(struct cfg_kw_list *kwl)
9078{
9079 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9080}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009081
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009082/*
9083 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9084 */
9085void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9086{
9087 LIST_DEL(&kwl->list);
9088 LIST_INIT(&kwl->list);
9089}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009090
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009091/* this function register new section in the haproxy configuration file.
9092 * <section_name> is the name of this new section and <section_parser>
9093 * is the called parser. If two section declaration have the same name,
9094 * only the first declared is used.
9095 */
9096int cfg_register_section(char *section_name,
9097 int (*section_parser)(const char *, int, char **, int))
9098{
9099 struct cfg_section *cs;
9100
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009101 list_for_each_entry(cs, &sections, list) {
9102 if (strcmp(cs->section_name, section_name) == 0) {
9103 Alert("register section '%s': already registered.\n", section_name);
9104 return 0;
9105 }
9106 }
9107
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009108 cs = calloc(1, sizeof(*cs));
9109 if (!cs) {
9110 Alert("register section '%s': out of memory.\n", section_name);
9111 return 0;
9112 }
9113
9114 cs->section_name = section_name;
9115 cs->section_parser = section_parser;
9116
9117 LIST_ADDQ(&sections, &cs->list);
9118
9119 return 1;
9120}
9121
Willy Tarreaubaaee002006-06-26 02:48:02 +02009122/*
David Carlier845efb52015-09-25 11:49:18 +01009123 * free all config section entries
9124 */
9125void cfg_unregister_sections(void)
9126{
9127 struct cfg_section *cs, *ics;
9128
9129 list_for_each_entry_safe(cs, ics, &sections, list) {
9130 LIST_DEL(&cs->list);
9131 free(cs);
9132 }
9133}
9134
9135/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009136 * Local variables:
9137 * c-indent-level: 8
9138 * c-basic-offset: 8
9139 * End:
9140 */