blob: f2181bc05088d8251477296d94b6c4863c79a9fd [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é2c8d7002014-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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau1c3a6122015-05-01 15:37:53 +0200154 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int 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 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
283 ss = *ss2;
284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 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 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200543 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 if (!strcmp(args[0], "global")) { /* new section */
546 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200549 else if (!strcmp(args[0], "ca-base")) {
550#ifdef USE_OPENSSL
551 if (global.ca_base != NULL) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.ca_base = strdup(args[1]);
562#else
563 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566#endif
567 }
568 else if (!strcmp(args[0], "crt-base")) {
569#ifdef USE_OPENSSL
570 if (global.crt_base != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT;
573 goto out;
574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.crt_base = strdup(args[1]);
581#else
582 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585#endif
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 else if (!strcmp(args[0], "daemon")) {
588 global.mode |= MODE_DAEMON;
589 }
590 else if (!strcmp(args[0], "debug")) {
591 global.mode |= MODE_DEBUG;
592 }
593 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100594 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200596 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100602 else if (!strcmp(args[0], "nosplice")) {
603 global.tune.options &= ~GTUNE_USE_SPLICE;
604 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605 else if (!strcmp(args[0], "nogetaddrinfo")) {
606 global.tune.options &= ~GTUNE_USE_GAI;
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "quiet")) {
609 global.mode |= MODE_QUIET;
610 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200611 else if (!strcmp(args[0], "tune.maxpollevents")) {
612 if (global.tune.maxpollevents != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200621 }
622 global.tune.maxpollevents = atol(args[1]);
623 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100624 else if (!strcmp(args[0], "tune.maxaccept")) {
625 if (global.tune.maxaccept != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100634 }
635 global.tune.maxaccept = atol(args[1]);
636 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200637 else if (!strcmp(args[0], "tune.chksize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.chksize = atol(args[1]);
644 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200645#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200646 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
647 global.tune.sslprivatecache = 1;
648 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100649 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.sslcachesize = atol(args[1]);
656 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100657 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
658 unsigned int ssllifetime;
659 const char *res;
660
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666
667 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
668 if (res) {
669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
670 file, linenum, *res, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 global.tune.ssllifetime = ssllifetime;
676 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100677 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.ssl_max_record = atol(args[1]);
684 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200685 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.ssl_default_dh_param = atol(args[1]);
692 if (global.tune.ssl_default_dh_param < 1024) {
693 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200698#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200699 else if (!strcmp(args[0], "tune.bufsize")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.bufsize = atol(args[1]);
Willy Tarreau47c7d632015-09-28 13:49:53 +0200706 if (global.tune.bufsize <= 0) {
707 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200711 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
712 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100713 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100714 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200715 }
716 else if (!strcmp(args[0], "tune.maxrewrite")) {
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.tune.maxrewrite = atol(args[1]);
723 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
724 global.tune.maxrewrite = global.tune.bufsize / 2;
725 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100726 else if (!strcmp(args[0], "tune.idletimer")) {
727 unsigned int idle;
728 const char *res;
729
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735
736 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
737 if (res) {
738 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
739 file, linenum, *res, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743
744 if (idle > 65535) {
745 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749 global.tune.idle_timer = idle;
750 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100751 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
752 if (global.tune.client_rcvbuf != 0) {
753 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT;
755 goto out;
756 }
757 if (*(args[1]) == 0) {
758 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762 global.tune.client_rcvbuf = atol(args[1]);
763 }
764 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
765 if (global.tune.server_rcvbuf != 0) {
766 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT;
768 goto out;
769 }
770 if (*(args[1]) == 0) {
771 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 global.tune.server_rcvbuf = atol(args[1]);
776 }
777 else if (!strcmp(args[0], "tune.sndbuf.client")) {
778 if (global.tune.client_sndbuf != 0) {
779 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT;
781 goto out;
782 }
783 if (*(args[1]) == 0) {
784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788 global.tune.client_sndbuf = atol(args[1]);
789 }
790 else if (!strcmp(args[0], "tune.sndbuf.server")) {
791 if (global.tune.server_sndbuf != 0) {
792 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT;
794 goto out;
795 }
796 if (*(args[1]) == 0) {
797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801 global.tune.server_sndbuf = atol(args[1]);
802 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200803 else if (!strcmp(args[0], "tune.pipesize")) {
804 if (*(args[1]) == 0) {
805 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 global.tune.pipesize = atol(args[1]);
810 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100811 else if (!strcmp(args[0], "tune.http.cookielen")) {
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.cookie_len = atol(args[1]) + 1;
818 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200819 else if (!strcmp(args[0], "tune.http.maxhdr")) {
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.max_http_hdr = atol(args[1]);
826 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100827 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
828#ifdef USE_ZLIB
829 if (*args[1]) {
830 global.tune.zlibmemlevel = atoi(args[1]);
831 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
832 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
833 file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837 } else {
838 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
839 file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843#else
844 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847#endif
848 }
849 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
850#ifdef USE_ZLIB
851 if (*args[1]) {
852 global.tune.zlibwindowsize = atoi(args[1]);
853 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 } else {
860 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
861 file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865#else
866 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869#endif
870 }
William Lallemandf3747832012-11-09 12:33:10 +0100871 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
872 if (*args[1]) {
873 global.tune.comp_maxlevel = atoi(args[1]);
874 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 } else {
881 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
882 file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 else if (!strcmp(args[0], "uid")) {
888 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200889 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
898 global.uid = atol(args[1]);
899 }
900 else if (!strcmp(args[0], "gid")) {
901 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200902 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 global.gid = atol(args[1]);
912 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200913 /* user/group name handling */
914 else if (!strcmp(args[0], "user")) {
915 struct passwd *ha_user;
916 if (global.uid != 0) {
917 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200918 err_code |= ERR_ALERT;
919 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200920 }
921 errno = 0;
922 ha_user = getpwnam(args[1]);
923 if (ha_user != NULL) {
924 global.uid = (int)ha_user->pw_uid;
925 }
926 else {
927 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 +0200928 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200929 }
930 }
931 else if (!strcmp(args[0], "group")) {
932 struct group *ha_group;
933 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200934 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200937 }
938 errno = 0;
939 ha_group = getgrnam(args[1]);
940 if (ha_group != NULL) {
941 global.gid = (int)ha_group->gr_gid;
942 }
943 else {
944 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 +0200945 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200946 }
947 }
948 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 if (*(args[1]) == 0) {
951 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 }
955 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100956 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
957 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
958 file, linenum, args[0], LONGBITS, global.nbproc);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto out;
961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 else if (!strcmp(args[0], "maxconn")) {
964 if (global.maxconn != 0) {
965 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 global.maxconn = atol(args[1]);
975#ifdef SYSTEM_MAXCONN
976 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
977 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);
978 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200979 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 }
981#endif /* SYSTEM_MAXCONN */
982 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200983 else if (!strcmp(args[0], "maxsslconn")) {
984#ifdef USE_OPENSSL
985 if (*(args[1]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
989 }
990 global.maxsslconn = atol(args[1]);
991#else
Emeric Brun0914df82012-10-02 18:45:42 +0200992 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
993 err_code |= ERR_ALERT | ERR_FATAL;
994 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200995#endif
996 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100997 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
998#ifdef USE_OPENSSL
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 free(global.listen_default_ciphers);
1005 global.listen_default_ciphers = strdup(args[1]);
1006#else
1007 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010#endif
1011 }
1012 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1013#ifdef USE_OPENSSL
1014 if (*(args[1]) == 0) {
1015 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
1019 free(global.connect_default_ciphers);
1020 global.connect_default_ciphers = strdup(args[1]);
1021#else
1022 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025#endif
1026 }
Emeric Brun850efd52014-01-29 12:24:34 +01001027 else if (!strcmp(args[0], "ssl-server-verify")) {
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
1033 if (strcmp(args[1],"none") == 0)
1034 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1035 else if (strcmp(args[1],"required") == 0)
1036 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1037 else {
1038 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001043 else if (!strcmp(args[0], "maxconnrate")) {
1044 if (global.cps_lim != 0) {
1045 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1046 err_code |= ERR_ALERT;
1047 goto out;
1048 }
1049 if (*(args[1]) == 0) {
1050 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053 }
1054 global.cps_lim = atol(args[1]);
1055 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001056 else if (!strcmp(args[0], "maxsessrate")) {
1057 if (global.sps_lim != 0) {
1058 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT;
1060 goto out;
1061 }
1062 if (*(args[1]) == 0) {
1063 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
1066 }
1067 global.sps_lim = atol(args[1]);
1068 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001069 else if (!strcmp(args[0], "maxsslrate")) {
1070 if (global.ssl_lim != 0) {
1071 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT;
1073 goto out;
1074 }
1075 if (*(args[1]) == 0) {
1076 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
1079 }
1080 global.ssl_lim = atol(args[1]);
1081 }
William Lallemandd85f9172012-11-09 17:05:39 +01001082 else if (!strcmp(args[0], "maxcomprate")) {
1083 if (*(args[1]) == 0) {
1084 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088 global.comp_rate_lim = atoi(args[1]) * 1024;
1089 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001090 else if (!strcmp(args[0], "maxpipes")) {
1091 if (global.maxpipes != 0) {
1092 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 err_code |= ERR_ALERT;
1094 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001095 }
1096 if (*(args[1]) == 0) {
1097 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001100 }
1101 global.maxpipes = atol(args[1]);
1102 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001103 else if (!strcmp(args[0], "maxzlibmem")) {
1104 if (*(args[1]) == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
1108 }
William Lallemande3a7d992012-11-20 11:25:20 +01001109 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001110 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001111 else if (!strcmp(args[0], "maxcompcpuusage")) {
1112 if (*(args[1]) == 0) {
1113 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001118 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001119 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123}
1124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 else if (!strcmp(args[0], "ulimit-n")) {
1126 if (global.rlimit_nofile != 0) {
1127 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 if (*(args[1]) == 0) {
1132 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 global.rlimit_nofile = atol(args[1]);
1137 }
1138 else if (!strcmp(args[0], "chroot")) {
1139 if (global.chroot != NULL) {
1140 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT;
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 if (*(args[1]) == 0) {
1145 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148 }
1149 global.chroot = strdup(args[1]);
1150 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001151 else if (!strcmp(args[0], "description")) {
1152 int i, len=0;
1153 char *d;
1154
1155 if (!*args[1]) {
1156 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1157 file, linenum, args[0]);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
1160 }
1161
Willy Tarreau348acfe2014-04-14 15:00:39 +02001162 for (i = 1; *args[i]; i++)
1163 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001164
1165 if (global.desc)
1166 free(global.desc);
1167
1168 global.desc = d = (char *)calloc(1, len);
1169
Willy Tarreau348acfe2014-04-14 15:00:39 +02001170 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1171 for (i = 2; *args[i]; i++)
1172 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001173 }
1174 else if (!strcmp(args[0], "node")) {
1175 int i;
1176 char c;
1177
1178 for (i=0; args[1][i]; i++) {
1179 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001180 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1181 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001182 break;
1183 }
1184
1185 if (!i || args[1][i]) {
1186 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1187 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1188 file, linenum, args[0]);
1189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
1191 }
1192
1193 if (global.node)
1194 free(global.node);
1195
1196 global.node = strdup(args[1]);
1197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 else if (!strcmp(args[0], "pidfile")) {
1199 if (global.pidfile != NULL) {
1200 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 }
1209 global.pidfile = strdup(args[1]);
1210 }
Emeric Bruned760922010-10-22 17:59:25 +02001211 else if (!strcmp(args[0], "unix-bind")) {
1212 int cur_arg = 1;
1213 while (*(args[cur_arg])) {
1214 if (!strcmp(args[cur_arg], "prefix")) {
1215 if (global.unix_bind.prefix != NULL) {
1216 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1217 err_code |= ERR_ALERT;
1218 cur_arg += 2;
1219 continue;
1220 }
1221
1222 if (*(args[cur_arg+1]) == 0) {
1223 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1228 cur_arg += 2;
1229 continue;
1230 }
1231
1232 if (!strcmp(args[cur_arg], "mode")) {
1233
1234 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1235 cur_arg += 2;
1236 continue;
1237 }
1238
1239 if (!strcmp(args[cur_arg], "uid")) {
1240
1241 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1242 cur_arg += 2;
1243 continue;
1244 }
1245
1246 if (!strcmp(args[cur_arg], "gid")) {
1247
1248 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1249 cur_arg += 2;
1250 continue;
1251 }
1252
1253 if (!strcmp(args[cur_arg], "user")) {
1254 struct passwd *user;
1255
1256 user = getpwnam(args[cur_arg + 1]);
1257 if (!user) {
1258 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1259 file, linenum, args[0], args[cur_arg + 1 ]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263
1264 global.unix_bind.ux.uid = user->pw_uid;
1265 cur_arg += 2;
1266 continue;
1267 }
1268
1269 if (!strcmp(args[cur_arg], "group")) {
1270 struct group *group;
1271
1272 group = getgrnam(args[cur_arg + 1]);
1273 if (!group) {
1274 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1275 file, linenum, args[0], args[cur_arg + 1 ]);
1276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
1279
1280 global.unix_bind.ux.gid = group->gr_gid;
1281 cur_arg += 2;
1282 continue;
1283 }
1284
Willy Tarreaub48f9582011-09-05 01:17:06 +02001285 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001286 file, linenum, args[0]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 }
William Lallemand0f99e342011-10-12 17:50:54 +02001291 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1292 /* delete previous herited or defined syslog servers */
1293 struct logsrv *back;
1294 struct logsrv *tmp;
1295
1296 if (*(args[1]) != 0) {
1297 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301
1302 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1303 LIST_DEL(&tmp->list);
1304 free(tmp);
1305 }
1306 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001308 struct sockaddr_storage *sk;
1309 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001310 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001311 int arg = 0;
1312 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001313
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314 if (*(args[1]) == 0 || *(args[2]) == 0) {
1315 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 }
William Lallemand0f99e342011-10-12 17:50:54 +02001319
1320 logsrv = calloc(1, sizeof(struct logsrv));
1321
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001322 /* just after the address, a length may be specified */
1323 if (strcmp(args[arg+2], "len") == 0) {
1324 len = atoi(args[arg+3]);
1325 if (len < 80 || len > 65535) {
1326 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1327 file, linenum, args[arg+3]);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331 logsrv->maxlen = len;
1332
1333 /* skip these two args */
1334 arg += 2;
1335 }
1336 else
1337 logsrv->maxlen = MAX_SYSLOG_LEN;
1338
1339 if (logsrv->maxlen > global.max_syslog_len) {
1340 global.max_syslog_len = logsrv->maxlen;
1341 logline = realloc(logline, global.max_syslog_len + 1);
1342 }
1343
1344 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001345 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001346 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001348 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 }
1350
William Lallemand0f99e342011-10-12 17:50:54 +02001351 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001352 if (*(args[arg+3])) {
1353 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001354 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001355 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001357 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 }
1360
William Lallemand0f99e342011-10-12 17:50:54 +02001361 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001362 if (*(args[arg+4])) {
1363 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001364 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001365 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001367 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001368 }
1369 }
1370
Willy Tarreau902636f2013-03-10 19:44:48 +01001371 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001372 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001373 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001375 free(logsrv);
1376 goto out;
1377 }
1378 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001379
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001380 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001381 if (port1 != port2) {
1382 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1383 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001384 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001385 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001386 goto out;
1387 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001388
William Lallemand0f99e342011-10-12 17:50:54 +02001389 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001390 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001391 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393
William Lallemand0f99e342011-10-12 17:50:54 +02001394 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001395 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001396 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1397 char *name;
1398 int len;
1399
1400 if (global.log_send_hostname != NULL) {
1401 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1402 err_code |= ERR_ALERT;
1403 goto out;
1404 }
1405
1406 if (*(args[1]))
1407 name = args[1];
1408 else
1409 name = hostname;
1410
1411 len = strlen(name);
1412
1413 /* We'll add a space after the name to respect the log format */
1414 free(global.log_send_hostname);
1415 global.log_send_hostname = malloc(len + 2);
1416 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1417 }
Kevinm48936af2010-12-22 16:08:21 +00001418 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1419 if (*(args[1]) == 0) {
1420 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
1423 }
1424 free(global.log_tag);
1425 global.log_tag = strdup(args[1]);
1426 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001427 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1428 if (global.spread_checks != 0) {
1429 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT;
1431 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001432 }
1433 if (*(args[1]) == 0) {
1434 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001435 err_code |= ERR_ALERT | ERR_FATAL;
1436 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001437 }
1438 global.spread_checks = atol(args[1]);
1439 if (global.spread_checks < 0 || global.spread_checks > 50) {
1440 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001441 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001444 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1445 const char *err;
1446 unsigned int val;
1447
1448
1449 if (*(args[1]) == 0) {
1450 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
1453 }
1454
1455 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1456 if (err) {
1457 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1458 err_code |= ERR_ALERT | ERR_FATAL;
1459 }
1460 global.max_spread_checks = val;
1461 if (global.max_spread_checks < 0) {
1462 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1463 err_code |= ERR_ALERT | ERR_FATAL;
1464 }
1465 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001466 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1467#ifdef USE_CPU_AFFINITY
1468 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001469 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001470 unsigned long cpus = 0;
1471
1472 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001473 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001474 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001475 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001476 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001477 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001478 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001479 proc = atol(args[1]);
1480 if (proc >= 1 && proc <= LONGBITS)
1481 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001482 }
1483
1484 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001485 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",
1486 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001487 err_code |= ERR_ALERT | ERR_FATAL;
1488 goto out;
1489 }
1490
1491 cur_arg = 2;
1492 while (*args[cur_arg]) {
1493 unsigned int low, high;
1494
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001495 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001496 char *dash = strchr(args[cur_arg], '-');
1497
1498 low = high = str2uic(args[cur_arg]);
1499 if (dash)
1500 high = str2uic(dash + 1);
1501
1502 if (high < low) {
1503 unsigned int swap = low;
1504 low = high;
1505 high = swap;
1506 }
1507
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001508 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001509 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001510 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 while (low <= high)
1516 cpus |= 1UL << low++;
1517 }
1518 else {
1519 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1520 file, linenum, args[0], args[cur_arg]);
1521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto out;
1523 }
1524 cur_arg++;
1525 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001526 for (i = 0; i < LONGBITS; i++)
1527 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001528 global.cpu_map[i] = cpus;
1529#else
1530 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533#endif
1534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001536 struct cfg_kw_list *kwl;
1537 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001538 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001539
1540 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1541 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1542 if (kwl->kw[index].section != CFG_GLOBAL)
1543 continue;
1544 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001545 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001546 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001547 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001548 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001549 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001550 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001551 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001552 err_code |= ERR_WARN;
1553 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001554 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001555 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001556 }
1557 }
1558 }
1559
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001563
Willy Tarreau058e9072009-07-20 09:30:05 +02001564 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001565 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001566 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567}
1568
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001569void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001571 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 defproxy.mode = PR_MODE_TCP;
1573 defproxy.state = PR_STNEW;
1574 defproxy.maxconn = cfg_maxpconn;
1575 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001576
Simon Horman66183002013-02-23 10:16:43 +09001577 defproxy.defsrv.check.inter = DEF_CHKINTR;
1578 defproxy.defsrv.check.fastinter = 0;
1579 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001580 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1581 defproxy.defsrv.agent.fastinter = 0;
1582 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001583 defproxy.defsrv.check.rise = DEF_RISETIME;
1584 defproxy.defsrv.check.fall = DEF_FALLTIME;
1585 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1586 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001587 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001588 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001589 defproxy.defsrv.maxqueue = 0;
1590 defproxy.defsrv.minconn = 0;
1591 defproxy.defsrv.maxconn = 0;
1592 defproxy.defsrv.slowstart = 0;
1593 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1594 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1595 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596}
1597
Willy Tarreauade5ec42010-01-28 19:33:49 +01001598
Willy Tarreau63af98d2014-05-18 08:11:41 +02001599/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1600 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1601 * ERR_FATAL in case of error.
1602 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001603static int create_cond_regex_rule(const char *file, int line,
1604 struct proxy *px, int dir, int action, int flags,
1605 const char *cmd, const char *reg, const char *repl,
1606 const char **cond_start)
1607{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001608 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001609 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001610 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001611 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001612 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001613 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001614 int cs;
1615 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001616
1617 if (px == &defproxy) {
1618 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001619 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001620 goto err;
1621 }
1622
1623 if (*reg == 0) {
1624 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001625 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001626 goto err;
1627 }
1628
1629 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001630 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001631
Willy Tarreau5321c422010-01-28 20:35:13 +01001632 if (cond_start &&
1633 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001634 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1635 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1636 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001637 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001638 goto err;
1639 }
1640 }
1641 else if (cond_start && **cond_start) {
1642 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1643 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001644 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001645 goto err;
1646 }
1647
Willy Tarreau63af98d2014-05-18 08:11:41 +02001648 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001649 (dir == SMP_OPT_DIR_REQ) ?
1650 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1651 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1652 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001653
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001654 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001655 if (!preg) {
1656 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001657 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001658 goto err;
1659 }
1660
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001661 cs = !(flags & REG_ICASE);
1662 cap = !(flags & REG_NOSUB);
1663 error = NULL;
1664 if (!regex_comp(reg, preg, cs, cap, &error)) {
1665 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1666 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001667 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001668 goto err;
1669 }
1670
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001671 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001672 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001673 if (repl && err) {
1674 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1675 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_ALERT | ERR_FATAL;
1677 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001678 }
1679
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001680 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001681 ret_code |= ERR_WARN;
1682
1683 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001684
Willy Tarreau63af98d2014-05-18 08:11:41 +02001685 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001686 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001687 err:
1688 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001689 free(errmsg);
1690 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001691}
1692
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001694 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001695 * Returns the error code, 0 if OK, or any combination of :
1696 * - ERR_ABORT: must abort ASAP
1697 * - ERR_FATAL: we can continue parsing but not start the service
1698 * - ERR_WARN: a warning has been emitted
1699 * - ERR_ALERT: an alert has been emitted
1700 * Only the two first ones can stop processing, the two others are just
1701 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001703int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1704{
1705 static struct peers *curpeers = NULL;
1706 struct peer *newpeer = NULL;
1707 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001708 struct bind_conf *bind_conf;
1709 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001710 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001711 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001712
1713 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001714 if (!*args[1]) {
1715 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001716 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001717 goto out;
1718 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001719
1720 err = invalid_char(args[1]);
1721 if (err) {
1722 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1723 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001724 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001725 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001726 }
1727
1728 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1729 /*
1730 * If there are two proxies with the same name only following
1731 * combinations are allowed:
1732 */
1733 if (strcmp(curpeers->id, args[1]) == 0) {
1734 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1735 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1736 err_code |= ERR_WARN;
1737 }
1738 }
1739
1740 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1741 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1742 err_code |= ERR_ALERT | ERR_ABORT;
1743 goto out;
1744 }
1745
1746 curpeers->next = peers;
1747 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001748 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001749 curpeers->conf.line = linenum;
1750 curpeers->last_change = now.tv_sec;
1751 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001752 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001753 }
1754 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001755 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001756 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001757 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001758
1759 if (!*args[2]) {
1760 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1761 file, linenum, args[0]);
1762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
1764 }
1765
1766 err = invalid_char(args[1]);
1767 if (err) {
1768 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1769 file, linenum, *err, args[1]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
1774 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1775 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1776 err_code |= ERR_ALERT | ERR_ABORT;
1777 goto out;
1778 }
1779
1780 /* the peers are linked backwards first */
1781 curpeers->count++;
1782 newpeer->next = curpeers->remote;
1783 curpeers->remote = newpeer;
1784 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001785 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001786 newpeer->conf.line = linenum;
1787
1788 newpeer->last_change = now.tv_sec;
1789 newpeer->id = strdup(args[1]);
1790
Willy Tarreau902636f2013-03-10 19:44:48 +01001791 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001792 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001793 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001794 err_code |= ERR_ALERT | ERR_FATAL;
1795 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001796 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001797
1798 proto = protocol_by_family(sk->ss_family);
1799 if (!proto || !proto->connect) {
1800 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1801 file, linenum, args[0], args[1]);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001805
1806 if (port1 != port2) {
1807 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1808 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
1812
Willy Tarreau2aa38802013-02-20 19:20:59 +01001813 if (!port1) {
1814 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1815 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001819
Emeric Brun32da3c42010-09-23 18:39:19 +02001820 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001821 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001822 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001823 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001824
Emeric Brun32da3c42010-09-23 18:39:19 +02001825 if (strcmp(newpeer->id, localpeer) == 0) {
1826 /* Current is local peer, it define a frontend */
1827 newpeer->local = 1;
1828
1829 if (!curpeers->peers_fe) {
1830 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1831 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1832 err_code |= ERR_ALERT | ERR_ABORT;
1833 goto out;
1834 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001835
Willy Tarreau237250c2011-07-29 01:49:03 +02001836 init_new_proxy(curpeers->peers_fe);
1837 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001838
1839 curpeers->peers_fe->last_change = now.tv_sec;
1840 curpeers->peers_fe->id = strdup(args[1]);
1841 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001842 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001843 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001844 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001845 curpeers->peers_fe->accept = peer_accept;
1846 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001847 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1848 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreaucdb5e922015-05-01 19:12:05 +02001849 curpeers->peers_fe->bind_proc = 0; /* will be filled by users */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001850
1851 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1852
Willy Tarreau902636f2013-03-10 19:44:48 +01001853 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1854 if (errmsg && *errmsg) {
1855 indent_msg(&errmsg, 2);
1856 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001857 }
1858 else
1859 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1860 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001861 err_code |= ERR_FATAL;
1862 goto out;
1863 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001864
1865 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001866 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001867 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1868 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1869 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1870 l->accept = session_accept;
1871 l->handler = process_session;
1872 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1873 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1874 global.maxsock += l->maxconn;
1875 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001876 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001877 else {
1878 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1879 file, linenum, args[0], args[1],
1880 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1881 err_code |= ERR_FATAL;
1882 goto out;
1883 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001884 }
1885 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001886 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1887 curpeers->state = PR_STSTOPPED;
1888 }
1889 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1890 curpeers->state = PR_STNEW;
1891 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001892 else if (*args[0] != 0) {
1893 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
1896 }
1897
1898out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001899 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001900 return err_code;
1901}
1902
Willy Tarreau3842f002009-06-14 11:39:52 +02001903int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904{
1905 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001906 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001907 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001908 int rc;
1909 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001910 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001911 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001912 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001913 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001914 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (!strcmp(args[0], "listen"))
1917 rc = PR_CAP_LISTEN;
1918 else if (!strcmp(args[0], "frontend"))
1919 rc = PR_CAP_FE | PR_CAP_RS;
1920 else if (!strcmp(args[0], "backend"))
1921 rc = PR_CAP_BE | PR_CAP_RS;
1922 else if (!strcmp(args[0], "ruleset"))
1923 rc = PR_CAP_RS;
1924 else
1925 rc = PR_CAP_NONE;
1926
1927 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001928 struct ebpt_node *node;
1929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 if (!*args[1]) {
1931 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1932 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_ABORT;
1935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001937
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001938 err = invalid_char(args[1]);
1939 if (err) {
1940 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1941 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001943 }
1944
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001945 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1946 curproxy = container_of(node, struct proxy, conf.by_name);
1947
1948 if (strcmp(curproxy->id, args[1]) != 0)
1949 break;
1950
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001951 /*
1952 * If there are two proxies with the same name only following
1953 * combinations are allowed:
1954 *
1955 * listen backend frontend ruleset
1956 * listen - - - -
1957 * backend - - OK -
1958 * frontend - OK - -
1959 * ruleset - - - -
1960 */
1961
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001962 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1963 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001964 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1965 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1966 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001968 }
1969 }
1970
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1972 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_ALERT | ERR_ABORT;
1974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001976
Willy Tarreau97cb7802010-01-03 20:23:58 +01001977 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 curproxy->next = proxy;
1979 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001980 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1981 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001982 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001984 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001985 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986
1987 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001989 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001990
Willy Tarreau4348fad2012-09-20 16:48:07 +02001991 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1992
Willy Tarreau902636f2013-03-10 19:44:48 +01001993 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1994 if (errmsg && *errmsg) {
1995 indent_msg(&errmsg, 2);
1996 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001997 }
1998 else
1999 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2000 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_FATAL;
2002 goto out;
2003 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002004
Willy Tarreau4348fad2012-09-20 16:48:07 +02002005 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002006 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 }
2009
2010 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002011 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002012 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002013
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002016 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002017 curproxy->no_options = defproxy.no_options;
2018 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002019 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002020 curproxy->except_net = defproxy.except_net;
2021 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002022 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002023 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002025 if (defproxy.fwdfor_hdr_len) {
2026 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2027 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2028 }
2029
Willy Tarreaub86db342009-11-30 11:50:16 +01002030 if (defproxy.orgto_hdr_len) {
2031 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2032 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2033 }
2034
Mark Lamourinec2247f02012-01-04 13:02:01 -05002035 if (defproxy.server_id_hdr_len) {
2036 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2037 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2038 }
2039
Willy Tarreau977b8e42006-12-29 14:19:17 +01002040 if (curproxy->cap & PR_CAP_FE) {
2041 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002042 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002043 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044
2045 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002046 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2047 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048
2049 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051
Willy Tarreau977b8e42006-12-29 14:19:17 +01002052 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002053 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002054 curproxy->fullconn = defproxy.fullconn;
2055 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002056 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002058 if (defproxy.check_req) {
2059 curproxy->check_req = calloc(1, defproxy.check_len);
2060 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2061 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002062 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002064 if (defproxy.expect_str) {
2065 curproxy->expect_str = strdup(defproxy.expect_str);
2066 if (defproxy.expect_regex) {
2067 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002068 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2069 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002070 }
2071 }
2072
Willy Tarreau67402132012-05-31 20:40:20 +02002073 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 if (defproxy.cookie_name)
2075 curproxy->cookie_name = strdup(defproxy.cookie_name);
2076 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002077 if (defproxy.cookie_domain)
2078 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002079
Willy Tarreau31936852010-10-06 16:59:56 +02002080 if (defproxy.cookie_maxidle)
2081 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2082
2083 if (defproxy.cookie_maxlife)
2084 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2085
Emeric Brun647caf12009-06-30 17:57:00 +02002086 if (defproxy.rdp_cookie_name)
2087 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2088 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2089
Willy Tarreau01732802007-11-01 22:48:15 +01002090 if (defproxy.url_param_name)
2091 curproxy->url_param_name = strdup(defproxy.url_param_name);
2092 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002093
Benoitaffb4812009-03-25 13:02:10 +01002094 if (defproxy.hh_name)
2095 curproxy->hh_name = strdup(defproxy.hh_name);
2096 curproxy->hh_len = defproxy.hh_len;
2097 curproxy->hh_match_domain = defproxy.hh_match_domain;
2098
Willy Tarreauef9a3602012-12-08 22:29:20 +01002099 if (defproxy.conn_src.iface_name)
2100 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2101 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002102 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002103#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002104 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002105#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002108 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 if (defproxy.capture_name)
2110 curproxy->capture_name = strdup(defproxy.capture_name);
2111 curproxy->capture_namelen = defproxy.capture_namelen;
2112 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002116 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002117 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002118 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002119 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002120 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002121 curproxy->mon_net = defproxy.mon_net;
2122 curproxy->mon_mask = defproxy.mon_mask;
2123 if (defproxy.monitor_uri)
2124 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2125 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002126 if (defproxy.defbe.name)
2127 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002128
2129 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002130 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2131 if (curproxy->conf.logformat_string &&
2132 curproxy->conf.logformat_string != default_http_log_format &&
2133 curproxy->conf.logformat_string != default_tcp_log_format &&
2134 curproxy->conf.logformat_string != clf_http_log_format)
2135 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2136
2137 if (defproxy.conf.lfs_file) {
2138 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2139 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2140 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002141 }
2142
2143 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002144 curproxy->timeout.connect = defproxy.timeout.connect;
2145 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002146 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002147 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002148 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002149 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002150 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002151 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002152 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002153 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154 }
2155
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002157 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002158
2159 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002160 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002161 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002162 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002163 LIST_INIT(&node->list);
2164 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2165 }
2166
Willy Tarreau62a61232013-04-12 18:13:46 +02002167 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2168 if (curproxy->conf.uniqueid_format_string)
2169 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2170
2171 if (defproxy.conf.uif_file) {
2172 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2173 curproxy->conf.uif_line = defproxy.conf.uif_line;
2174 }
William Lallemanda73203e2012-03-12 12:48:57 +01002175
2176 /* copy default header unique id */
2177 if (defproxy.header_unique_id)
2178 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2179
William Lallemand82fe75c2012-10-23 10:25:10 +02002180 /* default compression options */
2181 if (defproxy.comp != NULL) {
2182 curproxy->comp = calloc(1, sizeof(struct comp));
2183 curproxy->comp->algos = defproxy.comp->algos;
2184 curproxy->comp->types = defproxy.comp->types;
2185 }
2186
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002188 curproxy->conf.used_listener_id = EB_ROOT;
2189 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002190
Willy Tarreau93893792009-07-23 13:19:11 +02002191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
2193 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2194 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002195 /* FIXME-20070101: we should do this too at the end of the
2196 * config parsing to free all default values.
2197 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002198 free(defproxy.check_req);
2199 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002200 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002201 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002202 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002203 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002204 free(defproxy.capture_name);
2205 free(defproxy.monitor_uri);
2206 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002207 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002208 free(defproxy.fwdfor_hdr_name);
2209 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002210 free(defproxy.orgto_hdr_name);
2211 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002212 free(defproxy.server_id_hdr_name);
2213 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002214 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002215 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002216 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002217 free(defproxy.expect_regex);
2218 defproxy.expect_regex = NULL;
2219 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002220
Willy Tarreau62a61232013-04-12 18:13:46 +02002221 if (defproxy.conf.logformat_string != default_http_log_format &&
2222 defproxy.conf.logformat_string != default_tcp_log_format &&
2223 defproxy.conf.logformat_string != clf_http_log_format)
2224 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002225
Willy Tarreau62a61232013-04-12 18:13:46 +02002226 free(defproxy.conf.uniqueid_format_string);
2227 free(defproxy.conf.lfs_file);
2228 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002229
Willy Tarreaua534fea2008-08-03 12:19:50 +02002230 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002231 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002232
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 /* we cannot free uri_auth because it might already be used */
2234 init_default_instance();
2235 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002236 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2237 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002238 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 }
2241 else if (curproxy == NULL) {
2242 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002246
2247 /* update the current file and line being parsed */
2248 curproxy->conf.args.file = curproxy->conf.file;
2249 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250
2251 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002252 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2253 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2254 if (err_code & ERR_FATAL)
2255 goto out;
2256 }
2257 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002258 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002259 int cur_arg;
2260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 if (curproxy == &defproxy) {
2262 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268
Willy Tarreau24709282013-03-10 21:32:12 +01002269 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002270 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002275
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002276 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002277
2278 /* use default settings for unix sockets */
2279 bind_conf->ux.uid = global.unix_bind.ux.uid;
2280 bind_conf->ux.gid = global.unix_bind.ux.gid;
2281 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002282
2283 /* NOTE: the following line might create several listeners if there
2284 * are comma-separated IPs or port ranges. So all further processing
2285 * will have to be applied to all listeners created after last_listen.
2286 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002287 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2288 if (errmsg && *errmsg) {
2289 indent_msg(&errmsg, 2);
2290 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002291 }
2292 else
2293 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2294 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002298
Willy Tarreau4348fad2012-09-20 16:48:07 +02002299 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2300 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002301 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002302 }
2303
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002304 cur_arg = 2;
2305 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002306 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002307 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002308 char *err;
2309
Willy Tarreau26982662012-09-12 23:17:10 +02002310 kw = bind_find_kw(args[cur_arg]);
2311 if (kw) {
2312 char *err = NULL;
2313 int code;
2314
2315 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002316 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2317 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002318 cur_arg += 1 + kw->skip ;
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322
Willy Tarreau4348fad2012-09-20 16:48:07 +02002323 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002324 err_code |= code;
2325
2326 if (code) {
2327 if (err && *err) {
2328 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002329 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002330 }
2331 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002332 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2333 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002334 if (code & ERR_FATAL) {
2335 free(err);
2336 cur_arg += 1 + kw->skip;
2337 goto out;
2338 }
2339 }
2340 free(err);
2341 cur_arg += 1 + kw->skip;
2342 continue;
2343 }
2344
Willy Tarreau8638f482012-09-18 18:01:17 +02002345 err = NULL;
2346 if (!bind_dumped) {
2347 bind_dump_kws(&err);
2348 indent_msg(&err, 4);
2349 bind_dumped = 1;
2350 }
2351
2352 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2353 file, linenum, args[0], args[1], args[cur_arg],
2354 err ? " Registered keywords :" : "", err ? err : "");
2355 free(err);
2356
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002359 }
Willy Tarreau93893792009-07-23 13:19:11 +02002360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002363 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 /* flush useless bits */
2373 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002376 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002377 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002379
Willy Tarreau1c47f852006-07-09 08:22:27 +02002380 if (!*args[1]) {
2381 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2382 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002385 }
2386
Willy Tarreaua534fea2008-08-03 12:19:50 +02002387 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002388 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002389 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002390 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002391 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2392
Willy Tarreau93893792009-07-23 13:19:11 +02002393 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2396 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2397 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2398 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2399 else {
2400 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
2404 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002405 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002406 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002407
2408 if (curproxy == &defproxy) {
2409 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2410 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002413 }
2414
2415 if (!*args[1]) {
2416 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002420 }
2421
2422 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002423 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002424
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002425 if (curproxy->uuid <= 0) {
2426 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002427 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002430 }
2431
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002432 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2433 if (node) {
2434 struct proxy *target = container_of(node, struct proxy, conf.id);
2435 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2436 file, linenum, proxy_type_str(curproxy), curproxy->id,
2437 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
2440 }
2441 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002442 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002443 else if (!strcmp(args[0], "description")) {
2444 int i, len=0;
2445 char *d;
2446
Cyril Bonté99ed3272010-01-24 23:29:44 +01002447 if (curproxy == &defproxy) {
2448 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2449 file, linenum, args[0]);
2450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
2452 }
2453
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002454 if (!*args[1]) {
2455 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2456 file, linenum, args[0]);
2457 return -1;
2458 }
2459
Willy Tarreau348acfe2014-04-14 15:00:39 +02002460 for (i = 1; *args[i]; i++)
2461 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002462
2463 d = (char *)calloc(1, len);
2464 curproxy->desc = d;
2465
Willy Tarreau348acfe2014-04-14 15:00:39 +02002466 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2467 for (i = 2; *args[i]; i++)
2468 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002469
2470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2472 curproxy->state = PR_STSTOPPED;
2473 }
2474 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2475 curproxy->state = PR_STNEW;
2476 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002477 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2478 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002479 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002480
2481 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002482 unsigned int low, high;
2483
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002484 if (strcmp(args[cur_arg], "all") == 0) {
2485 set = 0;
2486 break;
2487 }
2488 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002489 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002490 }
2491 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002492 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002493 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002494 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002495 char *dash = strchr(args[cur_arg], '-');
2496
2497 low = high = str2uic(args[cur_arg]);
2498 if (dash)
2499 high = str2uic(dash + 1);
2500
2501 if (high < low) {
2502 unsigned int swap = low;
2503 low = high;
2504 high = swap;
2505 }
2506
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002507 if (low < 1 || high > LONGBITS) {
2508 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2509 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002512 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002513 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002514 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002515 }
2516 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002517 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2518 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002521 }
2522 cur_arg++;
2523 }
2524 curproxy->bind_proc = set;
2525 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002526 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002527 if (curproxy == &defproxy) {
2528 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002531 }
2532
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002533 err = invalid_char(args[1]);
2534 if (err) {
2535 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2536 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002538 }
2539
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002540 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002541 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2542 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002545 }
2546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2548 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549
Willy Tarreau977b8e42006-12-29 14:19:17 +01002550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002552
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 if (*(args[1]) == 0) {
2554 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002559
Willy Tarreau67402132012-05-31 20:40:20 +02002560 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002561 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002562 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002563 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 curproxy->cookie_name = strdup(args[1]);
2565 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002566
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 cur_arg = 2;
2568 while (*(args[cur_arg])) {
2569 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002570 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002573 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002576 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
2578 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002579 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
2581 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002582 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002584 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002585 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002588 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002590 else if (!strcmp(args[cur_arg], "httponly")) {
2591 curproxy->ck_opts |= PR_CK_HTTPONLY;
2592 }
2593 else if (!strcmp(args[cur_arg], "secure")) {
2594 curproxy->ck_opts |= PR_CK_SECURE;
2595 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002596 else if (!strcmp(args[cur_arg], "domain")) {
2597 if (!*args[cur_arg + 1]) {
2598 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2599 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002602 }
2603
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002604 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002605 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002606 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2607 " dots nor does not start with a dot."
2608 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002609 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002610 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002611 }
2612
2613 err = invalid_domainchar(args[cur_arg + 1]);
2614 if (err) {
2615 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2616 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002619 }
2620
Willy Tarreau68a897b2009-12-03 23:28:34 +01002621 if (!curproxy->cookie_domain) {
2622 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2623 } else {
2624 /* one domain was already specified, add another one by
2625 * building the string which will be returned along with
2626 * the cookie.
2627 */
2628 char *new_ptr;
2629 int new_len = strlen(curproxy->cookie_domain) +
2630 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2631 new_ptr = malloc(new_len);
2632 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2633 free(curproxy->cookie_domain);
2634 curproxy->cookie_domain = new_ptr;
2635 }
Willy Tarreau31936852010-10-06 16:59:56 +02002636 cur_arg++;
2637 }
2638 else if (!strcmp(args[cur_arg], "maxidle")) {
2639 unsigned int maxidle;
2640 const char *res;
2641
2642 if (!*args[cur_arg + 1]) {
2643 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2644 file, linenum, args[cur_arg]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648
2649 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2650 if (res) {
2651 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2652 file, linenum, *res, args[cur_arg]);
2653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
2655 }
2656 curproxy->cookie_maxidle = maxidle;
2657 cur_arg++;
2658 }
2659 else if (!strcmp(args[cur_arg], "maxlife")) {
2660 unsigned int maxlife;
2661 const char *res;
2662
2663 if (!*args[cur_arg + 1]) {
2664 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2665 file, linenum, args[cur_arg]);
2666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669
2670 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2671 if (res) {
2672 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2673 file, linenum, *res, args[cur_arg]);
2674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
2676 }
2677 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002678 cur_arg++;
2679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002681 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 +02002682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 }
2686 cur_arg++;
2687 }
Willy Tarreau67402132012-05-31 20:40:20 +02002688 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2690 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002691 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }
2693
Willy Tarreau67402132012-05-31 20:40:20 +02002694 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2696 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002699
Willy Tarreau67402132012-05-31 20:40:20 +02002700 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002701 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2702 file, linenum);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002706 else if (!strcmp(args[0], "persist")) { /* persist */
2707 if (*(args[1]) == 0) {
2708 Alert("parsing [%s:%d] : missing persist method.\n",
2709 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002712 }
2713
2714 if (!strncmp(args[1], "rdp-cookie", 10)) {
2715 curproxy->options2 |= PR_O2_RDPC_PRST;
2716
Emeric Brunb982a3d2010-01-04 15:45:53 +01002717 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002718 const char *beg, *end;
2719
2720 beg = args[1] + 11;
2721 end = strchr(beg, ')');
2722
2723 if (!end || end == beg) {
2724 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2725 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002728 }
2729
2730 free(curproxy->rdp_cookie_name);
2731 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2732 curproxy->rdp_cookie_len = end-beg;
2733 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002734 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002735 free(curproxy->rdp_cookie_name);
2736 curproxy->rdp_cookie_name = strdup("msts");
2737 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2738 }
2739 else { /* syntax */
2740 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2741 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002744 }
2745 }
2746 else {
2747 Alert("parsing [%s:%d] : unknown persist method.\n",
2748 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002751 }
2752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002754 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002756 if (curproxy == &defproxy) {
2757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002764
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002766 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
2771 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002772 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 curproxy->appsession_name = strdup(args[1]);
2774 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2775 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002776 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2777 if (err) {
2778 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2779 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002782 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002783 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002784
Willy Tarreau51041c72007-09-09 21:56:53 +02002785 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2786 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_ALERT | ERR_ABORT;
2788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002790
2791 cur_arg = 6;
2792 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002793 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2794 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002795 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002796 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002797 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002798 } else if (!strcmp(args[cur_arg], "prefix")) {
2799 curproxy->options2 |= PR_O2_AS_PFX;
2800 } else if (!strcmp(args[cur_arg], "mode")) {
2801 if (!*args[cur_arg + 1]) {
2802 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2803 file, linenum, args[0], args[cur_arg]);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807
2808 cur_arg++;
2809 if (!strcmp(args[cur_arg], "query-string")) {
2810 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2811 curproxy->options2 |= PR_O2_AS_M_QS;
2812 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2813 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2814 curproxy->options2 |= PR_O2_AS_M_PP;
2815 } else {
2816 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
2820 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002821 cur_arg++;
2822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 } /* Url App Session */
2824 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002825 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002826 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002827
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 if (*(args[4]) == 0) {
2836 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2837 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002841 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 curproxy->capture_name = strdup(args[2]);
2843 curproxy->capture_namelen = strlen(curproxy->capture_name);
2844 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 curproxy->to_log |= LW_COOKIE;
2846 }
2847 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2848 struct cap_hdr *hdr;
2849
2850 if (curproxy == &defproxy) {
2851 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 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 }
2855
2856 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2857 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2858 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
2862
2863 hdr = calloc(sizeof(struct cap_hdr), 1);
2864 hdr->next = curproxy->req_cap;
2865 hdr->name = strdup(args[3]);
2866 hdr->namelen = strlen(args[3]);
2867 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002868 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 hdr->index = curproxy->nb_req_cap++;
2870 curproxy->req_cap = hdr;
2871 curproxy->to_log |= LW_REQHDR;
2872 }
2873 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2874 struct cap_hdr *hdr;
2875
2876 if (curproxy == &defproxy) {
2877 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 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 }
2881
2882 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2883 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2884 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
2888 hdr = calloc(sizeof(struct cap_hdr), 1);
2889 hdr->next = curproxy->rsp_cap;
2890 hdr->name = strdup(args[3]);
2891 hdr->namelen = strlen(args[3]);
2892 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002893 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 hdr->index = curproxy->nb_rsp_cap++;
2895 curproxy->rsp_cap = hdr;
2896 curproxy->to_log |= LW_RSPHDR;
2897 }
2898 else {
2899 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2900 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 }
2904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002906 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 if (*(args[1]) == 0) {
2910 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2911 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
2915 curproxy->conn_retries = atol(args[1]);
2916 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002917 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002918 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002919
2920 if (curproxy == &defproxy) {
2921 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
Willy Tarreau20b0de52012-12-24 15:45:22 +01002926 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2927 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2928 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2929 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002930 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002931 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2932 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 +01002933 file, linenum, args[0]);
2934 err_code |= ERR_WARN;
2935 }
2936
Willy Tarreauff011f22011-01-06 17:51:27 +01002937 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002938
Willy Tarreauff011f22011-01-06 17:51:27 +01002939 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002940 err_code |= ERR_ALERT | ERR_ABORT;
2941 goto out;
2942 }
2943
Willy Tarreau5002f572014-04-23 01:32:02 +02002944 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002945 err_code |= warnif_cond_conflicts(rule->cond,
2946 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2947 file, linenum);
2948
Willy Tarreauff011f22011-01-06 17:51:27 +01002949 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002950 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002951 else if (!strcmp(args[0], "http-response")) { /* response access control */
2952 struct http_res_rule *rule;
2953
2954 if (curproxy == &defproxy) {
2955 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959
2960 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2961 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2962 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2963 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2964 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2965 file, linenum, args[0]);
2966 err_code |= ERR_WARN;
2967 }
2968
2969 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2970
2971 if (!rule) {
2972 err_code |= ERR_ALERT | ERR_ABORT;
2973 goto out;
2974 }
2975
2976 err_code |= warnif_cond_conflicts(rule->cond,
2977 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2978 file, linenum);
2979
2980 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2981 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002982 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2983 /* set the header name and length into the proxy structure */
2984 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2985 err_code |= ERR_WARN;
2986
2987 if (!*args[1]) {
2988 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2989 file, linenum, args[0]);
2990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
2992 }
2993
2994 /* set the desired header name */
2995 free(curproxy->server_id_hdr_name);
2996 curproxy->server_id_hdr_name = strdup(args[1]);
2997 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2998 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002999 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003000 struct http_req_rule *rule;
3001
Willy Tarreaub099aca2008-10-12 17:26:37 +02003002 if (curproxy == &defproxy) {
3003 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003006 }
3007
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003008 /* emulate "block" using "http-request block". Since these rules are supposed to
3009 * be processed before all http-request rules, we put them into their own list
3010 * and will insert them at the end.
3011 */
3012 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3013 if (!rule) {
3014 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003015 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003016 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003017 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3018 err_code |= warnif_cond_conflicts(rule->cond,
3019 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3020 file, linenum);
3021 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003022
3023 if (!already_warned(WARN_BLOCK_DEPRECATED))
3024 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]);
3025
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003026 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003027 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003028 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003029
Cyril Bonté99ed3272010-01-24 23:29:44 +01003030 if (curproxy == &defproxy) {
3031 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
3034 }
3035
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003036 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003037 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3038 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003041 }
3042
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003043 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003044 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003045 err_code |= warnif_cond_conflicts(rule->cond,
3046 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3047 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003048 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003049 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003050 struct switching_rule *rule;
3051
Willy Tarreaub099aca2008-10-12 17:26:37 +02003052 if (curproxy == &defproxy) {
3053 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003056 }
3057
Willy Tarreau55ea7572007-06-17 19:56:27 +02003058 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003060
3061 if (*(args[1]) == 0) {
3062 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003065 }
3066
Willy Tarreauf51658d2014-04-23 01:21:56 +02003067 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3068 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3069 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3070 file, linenum, errmsg);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003074
Willy Tarreauf51658d2014-04-23 01:21:56 +02003075 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003076 }
3077
3078 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3079 rule->cond = cond;
3080 rule->be.name = strdup(args[1]);
3081 LIST_INIT(&rule->list);
3082 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3083 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003084 else if (strcmp(args[0], "use-server") == 0) {
3085 struct server_rule *rule;
3086
3087 if (curproxy == &defproxy) {
3088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092
3093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3094 err_code |= ERR_WARN;
3095
3096 if (*(args[1]) == 0) {
3097 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101
3102 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3103 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3104 file, linenum, args[0]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003109 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3110 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3111 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
3114 }
3115
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003116 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003117
3118 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3119 rule->cond = cond;
3120 rule->srv.name = strdup(args[1]);
3121 LIST_INIT(&rule->list);
3122 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3123 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3124 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003125 else if ((!strcmp(args[0], "force-persist")) ||
3126 (!strcmp(args[0], "ignore-persist"))) {
3127 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003128
3129 if (curproxy == &defproxy) {
3130 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134
3135 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3136 err_code |= ERR_WARN;
3137
Willy Tarreauef6494c2010-01-28 17:12:36 +01003138 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003139 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3140 file, linenum, args[0]);
3141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
3143 }
3144
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003145 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3146 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3147 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003152 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3153 * where force-persist is applied.
3154 */
3155 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003156
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003157 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003158 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003159 if (!strcmp(args[0], "force-persist")) {
3160 rule->type = PERSIST_TYPE_FORCE;
3161 } else {
3162 rule->type = PERSIST_TYPE_IGNORE;
3163 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003164 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003165 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003166 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003167 else if (!strcmp(args[0], "stick-table")) {
3168 int myidx = 1;
3169
Emeric Brun32da3c42010-09-23 18:39:19 +02003170 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003171 curproxy->table.type = (unsigned int)-1;
3172 while (*args[myidx]) {
3173 const char *err;
3174
3175 if (strcmp(args[myidx], "size") == 0) {
3176 myidx++;
3177 if (!*(args[myidx])) {
3178 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3179 file, linenum, args[myidx-1]);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3184 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3185 file, linenum, *err, args[myidx-1]);
3186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
3188 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003189 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003190 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003191 else if (strcmp(args[myidx], "peers") == 0) {
3192 myidx++;
Godbach50523162013-12-11 19:48:57 +08003193 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003194 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3195 file, linenum, args[myidx-1]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Godbach50523162013-12-11 19:48:57 +08003198 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003199 curproxy->table.peers.name = strdup(args[myidx++]);
3200 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003201 else if (strcmp(args[myidx], "expire") == 0) {
3202 myidx++;
3203 if (!*(args[myidx])) {
3204 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3205 file, linenum, args[myidx-1]);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
3209 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3210 if (err) {
3211 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3212 file, linenum, *err, args[myidx-1]);
3213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
3215 }
Ben Cabot85a1c182016-01-20 09:44:39 +00003216 if (val > INT_MAX) {
3217 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3218 file, linenum, val);
3219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
3221 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003223 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003224 }
3225 else if (strcmp(args[myidx], "nopurge") == 0) {
3226 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003227 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003228 }
3229 else if (strcmp(args[myidx], "type") == 0) {
3230 myidx++;
3231 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3232 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3233 file, linenum, args[myidx]);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003237 /* myidx already points to next arg */
3238 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003239 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003240 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003241 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003242
3243 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003244 nw = args[myidx];
3245 while (*nw) {
3246 /* the "store" keyword supports a comma-separated list */
3247 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003248 sa = NULL; /* store arg */
3249 while (*nw && *nw != ',') {
3250 if (*nw == '(') {
3251 *nw = 0;
3252 sa = ++nw;
3253 while (*nw != ')') {
3254 if (!*nw) {
3255 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3256 file, linenum, args[0], cw);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260 nw++;
3261 }
3262 *nw = '\0';
3263 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003264 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003265 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003266 if (*nw)
3267 *nw++ = '\0';
3268 type = stktable_get_data_type(cw);
3269 if (type < 0) {
3270 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3271 file, linenum, args[0], cw);
3272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
3274 }
Willy Tarreauac782882010-06-20 10:41:54 +02003275
3276 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3277 switch (err) {
3278 case PE_NONE: break;
3279 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003280 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3281 file, linenum, args[0], cw);
3282 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003283 break;
3284
3285 case PE_ARG_MISSING:
3286 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3287 file, linenum, args[0], cw);
3288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
3290
3291 case PE_ARG_NOT_USED:
3292 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3293 file, linenum, args[0], cw);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296
3297 default:
3298 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3299 file, linenum, args[0], cw);
3300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003302 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003303 }
3304 myidx++;
3305 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003306 else {
3307 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3308 file, linenum, args[myidx]);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003311 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003312 }
3313
3314 if (!curproxy->table.size) {
3315 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3316 file, linenum);
3317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
3319 }
3320
3321 if (curproxy->table.type == (unsigned int)-1) {
3322 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3323 file, linenum);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326 }
3327 }
3328 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003329 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003330 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003331 int myidx = 0;
3332 const char *name = NULL;
3333 int flags;
3334
3335 if (curproxy == &defproxy) {
3336 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
3339 }
3340
3341 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3342 err_code |= ERR_WARN;
3343 goto out;
3344 }
3345
3346 myidx++;
3347 if ((strcmp(args[myidx], "store") == 0) ||
3348 (strcmp(args[myidx], "store-request") == 0)) {
3349 myidx++;
3350 flags = STK_IS_STORE;
3351 }
3352 else if (strcmp(args[myidx], "store-response") == 0) {
3353 myidx++;
3354 flags = STK_IS_STORE | STK_ON_RSP;
3355 }
3356 else if (strcmp(args[myidx], "match") == 0) {
3357 myidx++;
3358 flags = STK_IS_MATCH;
3359 }
3360 else if (strcmp(args[myidx], "on") == 0) {
3361 myidx++;
3362 flags = STK_IS_MATCH | STK_IS_STORE;
3363 }
3364 else {
3365 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
3368 }
3369
3370 if (*(args[myidx]) == 0) {
3371 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
3374 }
3375
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003376 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003377 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003378 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003379 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383
3384 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003385 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3386 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3387 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003388 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003389 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003390 goto out;
3391 }
3392 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003393 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3394 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3395 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003396 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003397 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003398 goto out;
3399 }
3400 }
3401
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003402 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003403 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003404
Emeric Brunb982a3d2010-01-04 15:45:53 +01003405 if (strcmp(args[myidx], "table") == 0) {
3406 myidx++;
3407 name = args[myidx++];
3408 }
3409
Willy Tarreauef6494c2010-01-28 17:12:36 +01003410 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003411 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3412 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3413 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003414 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003415 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003416 goto out;
3417 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003418 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003419 else if (*(args[myidx])) {
3420 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3421 file, linenum, args[0], args[myidx]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003423 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003424 goto out;
3425 }
Emeric Brun97679e72010-09-23 17:56:44 +02003426 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003427 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003428 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003429 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003430
Emeric Brunb982a3d2010-01-04 15:45:53 +01003431 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3432 rule->cond = cond;
3433 rule->expr = expr;
3434 rule->flags = flags;
3435 rule->table.name = name ? strdup(name) : NULL;
3436 LIST_INIT(&rule->list);
3437 if (flags & STK_ON_RSP)
3438 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3439 else
3440 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 else if (!strcmp(args[0], "stats")) {
3443 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3444 curproxy->uri_auth = NULL; /* we must detach from the default config */
3445
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003446 if (!*args[1]) {
3447 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003448 } else if (!strcmp(args[1], "admin")) {
3449 struct stats_admin_rule *rule;
3450
3451 if (curproxy == &defproxy) {
3452 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456
3457 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3458 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3459 err_code |= ERR_ALERT | ERR_ABORT;
3460 goto out;
3461 }
3462
3463 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3464 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3465 file, linenum, args[0], args[1]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003469 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3470 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3471 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
3475
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003476 err_code |= warnif_cond_conflicts(cond,
3477 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3478 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003479
3480 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3481 rule->cond = cond;
3482 LIST_INIT(&rule->list);
3483 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 } else if (!strcmp(args[1], "uri")) {
3485 if (*(args[2]) == 0) {
3486 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3490 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_ABORT;
3492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 }
3494 } else if (!strcmp(args[1], "realm")) {
3495 if (*(args[2]) == 0) {
3496 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3500 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_ABORT;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003504 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003505 unsigned interval;
3506
3507 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3508 if (err) {
3509 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3510 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003513 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3514 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_ABORT;
3516 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003517 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003518 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003519 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003520
3521 if (curproxy == &defproxy) {
3522 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
3525 }
3526
3527 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3528 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3529 err_code |= ERR_ALERT | ERR_ABORT;
3530 goto out;
3531 }
3532
Willy Tarreauff011f22011-01-06 17:51:27 +01003533 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3534 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003535 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3536 file, linenum, args[0]);
3537 err_code |= ERR_WARN;
3538 }
3539
Willy Tarreauff011f22011-01-06 17:51:27 +01003540 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003541
Willy Tarreauff011f22011-01-06 17:51:27 +01003542 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003543 err_code |= ERR_ALERT | ERR_ABORT;
3544 goto out;
3545 }
3546
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003547 err_code |= warnif_cond_conflicts(rule->cond,
3548 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3549 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003550 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003551
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 } else if (!strcmp(args[1], "auth")) {
3553 if (*(args[2]) == 0) {
3554 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3558 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_ALERT | ERR_ABORT;
3560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 }
3562 } else if (!strcmp(args[1], "scope")) {
3563 if (*(args[2]) == 0) {
3564 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_ABORT;
3570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 }
3572 } else if (!strcmp(args[1], "enable")) {
3573 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_ABORT;
3576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003578 } else if (!strcmp(args[1], "hide-version")) {
3579 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3580 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_ABORT;
3582 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003583 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003584 } else if (!strcmp(args[1], "show-legends")) {
3585 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3586 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3587 err_code |= ERR_ALERT | ERR_ABORT;
3588 goto out;
3589 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003590 } else if (!strcmp(args[1], "show-node")) {
3591
3592 if (*args[2]) {
3593 int i;
3594 char c;
3595
3596 for (i=0; args[2][i]; i++) {
3597 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003598 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3599 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003600 break;
3601 }
3602
3603 if (!i || args[2][i]) {
3604 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3605 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3606 file, linenum, args[0], args[1]);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
3609 }
3610 }
3611
3612 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3613 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3614 err_code |= ERR_ALERT | ERR_ABORT;
3615 goto out;
3616 }
3617 } else if (!strcmp(args[1], "show-desc")) {
3618 char *desc = NULL;
3619
3620 if (*args[2]) {
3621 int i, len=0;
3622 char *d;
3623
Willy Tarreau348acfe2014-04-14 15:00:39 +02003624 for (i = 2; *args[i]; i++)
3625 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003626
3627 desc = d = (char *)calloc(1, len);
3628
Willy Tarreau348acfe2014-04-14 15:00:39 +02003629 d += snprintf(d, desc + len - d, "%s", args[2]);
3630 for (i = 3; *args[i]; i++)
3631 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003632 }
3633
3634 if (!*args[2] && !global.desc)
3635 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3636 file, linenum, args[1]);
3637 else {
3638 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3639 free(desc);
3640 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3641 err_code |= ERR_ALERT | ERR_ABORT;
3642 goto out;
3643 }
3644 free(desc);
3645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003647stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003648 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 +01003649 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
3653 }
3654 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003655 int optnum;
3656
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003657 if (*(args[1]) == '\0') {
3658 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003663
3664 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3665 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003666 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3667 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3668 file, linenum, cfg_opts[optnum].name);
3669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
3671 }
Willy Tarreau93893792009-07-23 13:19:11 +02003672 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3673 err_code |= ERR_WARN;
3674 goto out;
3675 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003676
Willy Tarreau3842f002009-06-14 11:39:52 +02003677 curproxy->no_options &= ~cfg_opts[optnum].val;
3678 curproxy->options &= ~cfg_opts[optnum].val;
3679
3680 switch (kwm) {
3681 case KWM_STD:
3682 curproxy->options |= cfg_opts[optnum].val;
3683 break;
3684 case KWM_NO:
3685 curproxy->no_options |= cfg_opts[optnum].val;
3686 break;
3687 case KWM_DEF: /* already cleared */
3688 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003689 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003690
Willy Tarreau93893792009-07-23 13:19:11 +02003691 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003692 }
3693 }
3694
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003695 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3696 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003697 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3698 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3699 file, linenum, cfg_opts2[optnum].name);
3700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
3702 }
Willy Tarreau93893792009-07-23 13:19:11 +02003703 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3704 err_code |= ERR_WARN;
3705 goto out;
3706 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003707
Willy Tarreau3842f002009-06-14 11:39:52 +02003708 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3709 curproxy->options2 &= ~cfg_opts2[optnum].val;
3710
3711 switch (kwm) {
3712 case KWM_STD:
3713 curproxy->options2 |= cfg_opts2[optnum].val;
3714 break;
3715 case KWM_NO:
3716 curproxy->no_options2 |= cfg_opts2[optnum].val;
3717 break;
3718 case KWM_DEF: /* already cleared */
3719 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003720 }
Willy Tarreau93893792009-07-23 13:19:11 +02003721 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003722 }
3723 }
3724
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003725 /* HTTP options override each other. They can be cancelled using
3726 * "no option xxx" which only switches to default mode if the mode
3727 * was this one (useful for cancelling options set in defaults
3728 * sections).
3729 */
3730 if (strcmp(args[1], "httpclose") == 0) {
3731 if (kwm == KWM_STD) {
3732 curproxy->options &= ~PR_O_HTTP_MODE;
3733 curproxy->options |= PR_O_HTTP_PCL;
3734 goto out;
3735 }
3736 else if (kwm == KWM_NO) {
3737 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3738 curproxy->options &= ~PR_O_HTTP_MODE;
3739 goto out;
3740 }
3741 }
3742 else if (strcmp(args[1], "forceclose") == 0) {
3743 if (kwm == KWM_STD) {
3744 curproxy->options &= ~PR_O_HTTP_MODE;
3745 curproxy->options |= PR_O_HTTP_FCL;
3746 goto out;
3747 }
3748 else if (kwm == KWM_NO) {
3749 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3750 curproxy->options &= ~PR_O_HTTP_MODE;
3751 goto out;
3752 }
3753 }
3754 else if (strcmp(args[1], "http-server-close") == 0) {
3755 if (kwm == KWM_STD) {
3756 curproxy->options &= ~PR_O_HTTP_MODE;
3757 curproxy->options |= PR_O_HTTP_SCL;
3758 goto out;
3759 }
3760 else if (kwm == KWM_NO) {
3761 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3762 curproxy->options &= ~PR_O_HTTP_MODE;
3763 goto out;
3764 }
3765 }
3766 else if (strcmp(args[1], "http-keep-alive") == 0) {
3767 if (kwm == KWM_STD) {
3768 curproxy->options &= ~PR_O_HTTP_MODE;
3769 curproxy->options |= PR_O_HTTP_KAL;
3770 goto out;
3771 }
3772 else if (kwm == KWM_NO) {
3773 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3774 curproxy->options &= ~PR_O_HTTP_MODE;
3775 goto out;
3776 }
3777 }
3778 else if (strcmp(args[1], "http-tunnel") == 0) {
3779 if (kwm == KWM_STD) {
3780 curproxy->options &= ~PR_O_HTTP_MODE;
3781 curproxy->options |= PR_O_HTTP_TUN;
3782 goto out;
3783 }
3784 else if (kwm == KWM_NO) {
3785 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3786 curproxy->options &= ~PR_O_HTTP_MODE;
3787 goto out;
3788 }
3789 }
3790
Willy Tarreau3842f002009-06-14 11:39:52 +02003791 if (kwm != KWM_STD) {
3792 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003793 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003796 }
3797
Emeric Brun3a058f32009-06-30 18:26:00 +02003798 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003799 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003801 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003802 if (*(args[2]) != '\0') {
3803 if (!strcmp(args[2], "clf")) {
3804 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003805 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003806 } else {
William Lallemand629b1c02015-05-28 18:02:48 +02003807 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003810 }
3811 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003812 if (curproxy->conf.logformat_string != default_http_log_format &&
3813 curproxy->conf.logformat_string != default_tcp_log_format &&
3814 curproxy->conf.logformat_string != clf_http_log_format)
3815 free(curproxy->conf.logformat_string);
3816 curproxy->conf.logformat_string = logformat;
3817
3818 free(curproxy->conf.lfs_file);
3819 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3820 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003821 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003822 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003824 if (curproxy->conf.logformat_string != default_http_log_format &&
3825 curproxy->conf.logformat_string != default_tcp_log_format &&
3826 curproxy->conf.logformat_string != clf_http_log_format)
3827 free(curproxy->conf.logformat_string);
3828 curproxy->conf.logformat_string = default_tcp_log_format;
3829
3830 free(curproxy->conf.lfs_file);
3831 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3832 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 else if (!strcmp(args[1], "tcpka")) {
3835 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003836 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003837 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003838
3839 if (curproxy->cap & PR_CAP_FE)
3840 curproxy->options |= PR_O_TCP_CLI_KA;
3841 if (curproxy->cap & PR_CAP_BE)
3842 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 }
3844 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003845 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_WARN;
3847
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003849 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003850 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003851 curproxy->options2 &= ~PR_O2_CHK_ANY;
3852 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 if (!*args[2]) { /* no argument */
3854 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3855 curproxy->check_len = strlen(DEF_CHECK_REQ);
3856 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003857 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 curproxy->check_req = (char *)malloc(reqlen);
3859 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003860 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003862 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 if (*args[4])
3864 reqlen += strlen(args[4]);
3865 else
3866 reqlen += strlen("HTTP/1.0");
3867
3868 curproxy->check_req = (char *)malloc(reqlen);
3869 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003870 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003872 }
3873 else if (!strcmp(args[1], "ssl-hello-chk")) {
3874 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003877
Willy Tarreaua534fea2008-08-03 12:19:50 +02003878 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003879 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003880 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003881 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 }
Willy Tarreau23677902007-05-08 23:50:35 +02003883 else if (!strcmp(args[1], "smtpchk")) {
3884 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003885 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003886 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003887 curproxy->options2 &= ~PR_O2_CHK_ANY;
3888 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003889
3890 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3891 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3892 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3893 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3894 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3895 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3896 curproxy->check_req = (char *)malloc(reqlen);
3897 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3898 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3899 } else {
3900 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3901 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3902 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3903 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3904 }
3905 }
3906 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003907 else if (!strcmp(args[1], "pgsql-check")) {
3908 /* use PostgreSQL request to check servers' health */
3909 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3910 err_code |= ERR_WARN;
3911
3912 free(curproxy->check_req);
3913 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003914 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003915 curproxy->options2 |= PR_O2_PGSQL_CHK;
3916
3917 if (*(args[2])) {
3918 int cur_arg = 2;
3919
3920 while (*(args[cur_arg])) {
3921 if (strcmp(args[cur_arg], "user") == 0) {
3922 char * packet;
3923 uint32_t packet_len;
3924 uint32_t pv;
3925
3926 /* suboption header - needs additional argument for it */
3927 if (*(args[cur_arg+1]) == 0) {
3928 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3929 file, linenum, args[0], args[1], args[cur_arg]);
3930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
3932 }
3933
3934 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3935 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3936 pv = htonl(0x30000); /* protocol version 3.0 */
3937
3938 packet = (char*) calloc(1, packet_len);
3939
3940 memcpy(packet + 4, &pv, 4);
3941
3942 /* copy "user" */
3943 memcpy(packet + 8, "user", 4);
3944
3945 /* copy username */
3946 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3947
3948 free(curproxy->check_req);
3949 curproxy->check_req = packet;
3950 curproxy->check_len = packet_len;
3951
3952 packet_len = htonl(packet_len);
3953 memcpy(packet, &packet_len, 4);
3954 cur_arg += 2;
3955 } else {
3956 /* unknown suboption - catchall */
3957 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3958 file, linenum, args[0], args[1]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962 } /* end while loop */
3963 }
3964 }
3965
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003966 else if (!strcmp(args[1], "redis-check")) {
3967 /* use REDIS PING request to check servers' health */
3968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3969 err_code |= ERR_WARN;
3970
3971 free(curproxy->check_req);
3972 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003973 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003974 curproxy->options2 |= PR_O2_REDIS_CHK;
3975
3976 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3977 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3978 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3979 }
3980
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003981 else if (!strcmp(args[1], "mysql-check")) {
3982 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003983 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3984 err_code |= ERR_WARN;
3985
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003986 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003987 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003988 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003989 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003990
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003991 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003992 * const char mysql40_client_auth_pkt[] = {
3993 * "\x0e\x00\x00" // packet length
3994 * "\x01" // packet number
3995 * "\x00\x00" // client capabilities
3996 * "\x00\x00\x01" // max packet
3997 * "haproxy\x00" // username (null terminated string)
3998 * "\x00" // filler (always 0x00)
3999 * "\x01\x00\x00" // packet length
4000 * "\x00" // packet number
4001 * "\x01" // COM_QUIT command
4002 * };
4003 */
4004
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004005 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4006 * const char mysql41_client_auth_pkt[] = {
4007 * "\x0e\x00\x00\" // packet length
4008 * "\x01" // packet number
4009 * "\x00\x00\x00\x00" // client capabilities
4010 * "\x00\x00\x00\x01" // max packet
4011 * "\x21" // character set (UTF-8)
4012 * char[23] // All zeroes
4013 * "haproxy\x00" // username (null terminated string)
4014 * "\x00" // filler (always 0x00)
4015 * "\x01\x00\x00" // packet length
4016 * "\x00" // packet number
4017 * "\x01" // COM_QUIT command
4018 * };
4019 */
4020
4021
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004022 if (*(args[2])) {
4023 int cur_arg = 2;
4024
4025 while (*(args[cur_arg])) {
4026 if (strcmp(args[cur_arg], "user") == 0) {
4027 char *mysqluser;
4028 int packetlen, reqlen, userlen;
4029
4030 /* suboption header - needs additional argument for it */
4031 if (*(args[cur_arg+1]) == 0) {
4032 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4033 file, linenum, args[0], args[1], args[cur_arg]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037 mysqluser = args[cur_arg + 1];
4038 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004039
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004040 if (*(args[cur_arg+2])) {
4041 if (!strcmp(args[cur_arg+2], "post-41")) {
4042 packetlen = userlen + 7 + 27;
4043 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004044
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004045 free(curproxy->check_req);
4046 curproxy->check_req = (char *)calloc(1, reqlen);
4047 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004048
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004049 snprintf(curproxy->check_req, 4, "%c%c%c",
4050 ((unsigned char) packetlen & 0xff),
4051 ((unsigned char) (packetlen >> 8) & 0xff),
4052 ((unsigned char) (packetlen >> 16) & 0xff));
4053
4054 curproxy->check_req[3] = 1;
4055 curproxy->check_req[5] = 130;
4056 curproxy->check_req[11] = 1;
4057 curproxy->check_req[12] = 33;
4058 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4059 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4060 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4061 cur_arg += 3;
4062 } else {
4063 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
4066 }
4067 } else {
4068 packetlen = userlen + 7;
4069 reqlen = packetlen + 9;
4070
4071 free(curproxy->check_req);
4072 curproxy->check_req = (char *)calloc(1, reqlen);
4073 curproxy->check_len = reqlen;
4074
4075 snprintf(curproxy->check_req, 4, "%c%c%c",
4076 ((unsigned char) packetlen & 0xff),
4077 ((unsigned char) (packetlen >> 8) & 0xff),
4078 ((unsigned char) (packetlen >> 16) & 0xff));
4079
4080 curproxy->check_req[3] = 1;
4081 curproxy->check_req[5] = 128;
4082 curproxy->check_req[8] = 1;
4083 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4084 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4085 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4086 cur_arg += 2;
4087 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004088 } else {
4089 /* unknown suboption - catchall */
4090 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4091 file, linenum, args[0], args[1]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095 } /* end while loop */
4096 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004097 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004098 else if (!strcmp(args[1], "ldap-check")) {
4099 /* use LDAP request to check servers' health */
4100 free(curproxy->check_req);
4101 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004102 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004103 curproxy->options2 |= PR_O2_LDAP_CHK;
4104
4105 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4106 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4107 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4108 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004109 else if (!strcmp(args[1], "tcp-check")) {
4110 /* use raw TCPCHK send/expect to check servers' health */
4111 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4112 err_code |= ERR_WARN;
4113
4114 free(curproxy->check_req);
4115 curproxy->check_req = NULL;
4116 curproxy->options2 &= ~PR_O2_CHK_ANY;
4117 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4118 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004119 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004120 int cur_arg;
4121
4122 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4123 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004124 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004125
Willy Tarreau87cf5142011-08-19 22:57:24 +02004126 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004127
4128 free(curproxy->fwdfor_hdr_name);
4129 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4130 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4131
4132 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4133 cur_arg = 2;
4134 while (*(args[cur_arg])) {
4135 if (!strcmp(args[cur_arg], "except")) {
4136 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004137 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004138 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4139 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004142 }
4143 /* flush useless bits */
4144 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004145 cur_arg += 2;
4146 } else if (!strcmp(args[cur_arg], "header")) {
4147 /* suboption header - needs additional argument for it */
4148 if (*(args[cur_arg+1]) == 0) {
4149 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4150 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004153 }
4154 free(curproxy->fwdfor_hdr_name);
4155 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4156 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4157 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004158 } else if (!strcmp(args[cur_arg], "if-none")) {
4159 curproxy->options &= ~PR_O_FF_ALWAYS;
4160 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004161 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004162 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004163 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004164 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004167 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004168 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004169 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004170 else if (!strcmp(args[1], "originalto")) {
4171 int cur_arg;
4172
4173 /* insert x-original-to field, but not for the IP address listed as an except.
4174 * set default options (ie: bitfield, header name, etc)
4175 */
4176
4177 curproxy->options |= PR_O_ORGTO;
4178
4179 free(curproxy->orgto_hdr_name);
4180 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4181 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4182
Willy Tarreau87cf5142011-08-19 22:57:24 +02004183 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004184 cur_arg = 2;
4185 while (*(args[cur_arg])) {
4186 if (!strcmp(args[cur_arg], "except")) {
4187 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004188 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 +02004189 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4190 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004193 }
4194 /* flush useless bits */
4195 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4196 cur_arg += 2;
4197 } else if (!strcmp(args[cur_arg], "header")) {
4198 /* suboption header - needs additional argument for it */
4199 if (*(args[cur_arg+1]) == 0) {
4200 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4201 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004204 }
4205 free(curproxy->orgto_hdr_name);
4206 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4207 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4208 cur_arg += 2;
4209 } else {
4210 /* unknown suboption - catchall */
4211 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4212 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004215 }
4216 } /* end while loop */
4217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 else {
4219 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222 }
Willy Tarreau93893792009-07-23 13:19:11 +02004223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004225 else if (!strcmp(args[0], "default_backend")) {
4226 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004227 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004228
4229 if (*(args[1]) == 0) {
4230 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004233 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004234 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004235 curproxy->defbe.name = strdup(args[1]);
4236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004237 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004238 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004240
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004241 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4242 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 +01004243 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 /* enable reconnections to dispatch */
4246 curproxy->options |= PR_O_REDISP;
4247 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004248 else if (!strcmp(args[0], "http-check")) {
4249 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004250 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004251
4252 if (strcmp(args[1], "disable-on-404") == 0) {
4253 /* enable a graceful server shutdown on an HTTP 404 response */
4254 curproxy->options |= PR_O_DISABLE404;
4255 }
Willy Tarreauef781042010-01-27 11:53:01 +01004256 else if (strcmp(args[1], "send-state") == 0) {
4257 /* enable emission of the apparent state of a server in HTTP checks */
4258 curproxy->options2 |= PR_O2_CHK_SNDST;
4259 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004260 else if (strcmp(args[1], "expect") == 0) {
4261 const char *ptr_arg;
4262 int cur_arg;
4263
4264 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4265 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269
4270 cur_arg = 2;
4271 /* consider exclamation marks, sole or at the beginning of a word */
4272 while (*(ptr_arg = args[cur_arg])) {
4273 while (*ptr_arg == '!') {
4274 curproxy->options2 ^= PR_O2_EXP_INV;
4275 ptr_arg++;
4276 }
4277 if (*ptr_arg)
4278 break;
4279 cur_arg++;
4280 }
4281 /* now ptr_arg points to the beginning of a word past any possible
4282 * exclamation mark, and cur_arg is the argument which holds this word.
4283 */
4284 if (strcmp(ptr_arg, "status") == 0) {
4285 if (!*(args[cur_arg + 1])) {
4286 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4287 file, linenum, args[0], args[1], ptr_arg);
4288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
4291 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004292 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004293 curproxy->expect_str = strdup(args[cur_arg + 1]);
4294 }
4295 else if (strcmp(ptr_arg, "string") == 0) {
4296 if (!*(args[cur_arg + 1])) {
4297 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4298 file, linenum, args[0], args[1], ptr_arg);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004303 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004304 curproxy->expect_str = strdup(args[cur_arg + 1]);
4305 }
4306 else if (strcmp(ptr_arg, "rstatus") == 0) {
4307 if (!*(args[cur_arg + 1])) {
4308 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4309 file, linenum, args[0], args[1], ptr_arg);
4310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004314 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004315 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004316 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004317 free(curproxy->expect_regex);
4318 curproxy->expect_regex = NULL;
4319 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004320 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004321 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4322 error = NULL;
4323 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4324 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4325 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4326 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330 }
4331 else if (strcmp(ptr_arg, "rstring") == 0) {
4332 if (!*(args[cur_arg + 1])) {
4333 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4334 file, linenum, args[0], args[1], ptr_arg);
4335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
4337 }
4338 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004339 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004340 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004341 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004342 free(curproxy->expect_regex);
4343 curproxy->expect_regex = NULL;
4344 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004345 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004346 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4347 error = NULL;
4348 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4349 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4350 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4351 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004352 err_code |= ERR_ALERT | ERR_FATAL;
4353 goto out;
4354 }
4355 }
4356 else {
4357 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4358 file, linenum, args[0], args[1], ptr_arg);
4359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
4361 }
4362 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004363 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004364 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 +02004365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004367 }
4368 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004369 else if (!strcmp(args[0], "tcp-check")) {
4370 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4371 err_code |= ERR_WARN;
4372
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004373 if (strcmp(args[1], "connect") == 0) {
4374 const char *ptr_arg;
4375 int cur_arg;
4376 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004377
4378 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004379 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004380
Willy Tarreau5bff0592015-05-13 12:24:53 +02004381 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4382 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4383 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4384 file, linenum);
4385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004387 }
4388
4389 cur_arg = 2;
4390 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4391 tcpcheck->action = TCPCHK_ACT_CONNECT;
4392
4393 /* parsing each parameters to fill up the rule */
4394 while (*(ptr_arg = args[cur_arg])) {
4395 /* tcp port */
4396 if (strcmp(args[cur_arg], "port") == 0) {
4397 if ( (atol(args[cur_arg + 1]) > 65535) ||
4398 (atol(args[cur_arg + 1]) < 1) ){
4399 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4400 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
4403 }
4404 tcpcheck->port = atol(args[cur_arg + 1]);
4405 cur_arg += 2;
4406 }
4407 /* send proxy protocol */
4408 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4409 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4410 cur_arg++;
4411 }
4412#ifdef USE_OPENSSL
4413 else if (strcmp(args[cur_arg], "ssl") == 0) {
4414 curproxy->options |= PR_O_TCPCHK_SSL;
4415 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4416 cur_arg++;
4417 }
4418#endif /* USE_OPENSSL */
4419 else {
4420#ifdef USE_OPENSSL
4421 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4422#else /* USE_OPENSSL */
4423 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4424#endif /* USE_OPENSSL */
4425 file, linenum, args[0], args[1], args[cur_arg]);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
4429
4430 }
4431
4432 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4433 }
4434 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004435 if (! *(args[2]) ) {
4436 /* SEND string expected */
4437 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4438 file, linenum, args[0], args[1], args[2]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 } else {
4442 struct tcpcheck_rule *tcpcheck;
4443
4444 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4445
4446 tcpcheck->action = TCPCHK_ACT_SEND;
4447 tcpcheck->string_len = strlen(args[2]);
4448 tcpcheck->string = strdup(args[2]);
4449 tcpcheck->expect_regex = NULL;
4450
4451 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4452 }
4453 }
4454 else if (strcmp(args[1], "send-binary") == 0) {
4455 if (! *(args[2]) ) {
4456 /* SEND binary string expected */
4457 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4458 file, linenum, args[0], args[1], args[2]);
4459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
4461 } else {
4462 struct tcpcheck_rule *tcpcheck;
4463 char *err = NULL;
4464
4465 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4466
4467 tcpcheck->action = TCPCHK_ACT_SEND;
4468 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4469 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4470 file, linenum, args[0], args[1], args[2], err);
4471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
4473 }
4474 tcpcheck->expect_regex = NULL;
4475
4476 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4477 }
4478 }
4479 else if (strcmp(args[1], "expect") == 0) {
4480 const char *ptr_arg;
4481 int cur_arg;
4482 int inverse = 0;
4483
4484 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4485 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
4488 }
4489
4490 cur_arg = 2;
4491 /* consider exclamation marks, sole or at the beginning of a word */
4492 while (*(ptr_arg = args[cur_arg])) {
4493 while (*ptr_arg == '!') {
4494 inverse = !inverse;
4495 ptr_arg++;
4496 }
4497 if (*ptr_arg)
4498 break;
4499 cur_arg++;
4500 }
4501 /* now ptr_arg points to the beginning of a word past any possible
4502 * exclamation mark, and cur_arg is the argument which holds this word.
4503 */
4504 if (strcmp(ptr_arg, "binary") == 0) {
4505 if (!*(args[cur_arg + 1])) {
4506 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4507 file, linenum, args[0], args[1], ptr_arg);
4508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
4510 }
4511 struct tcpcheck_rule *tcpcheck;
4512 char *err = NULL;
4513
4514 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4515
4516 tcpcheck->action = TCPCHK_ACT_EXPECT;
4517 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4518 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4519 file, linenum, args[0], args[1], args[2], err);
4520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
4522 }
4523 tcpcheck->expect_regex = NULL;
4524 tcpcheck->inverse = inverse;
4525
4526 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4527 }
4528 else if (strcmp(ptr_arg, "string") == 0) {
4529 if (!*(args[cur_arg + 1])) {
4530 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4531 file, linenum, args[0], args[1], ptr_arg);
4532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
4534 }
4535 struct tcpcheck_rule *tcpcheck;
4536
4537 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4538
4539 tcpcheck->action = TCPCHK_ACT_EXPECT;
4540 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4541 tcpcheck->string = strdup(args[cur_arg + 1]);
4542 tcpcheck->expect_regex = NULL;
4543 tcpcheck->inverse = inverse;
4544
4545 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4546 }
4547 else if (strcmp(ptr_arg, "rstring") == 0) {
4548 if (!*(args[cur_arg + 1])) {
4549 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4550 file, linenum, args[0], args[1], ptr_arg);
4551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
4553 }
4554 struct tcpcheck_rule *tcpcheck;
4555
4556 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4557
4558 tcpcheck->action = TCPCHK_ACT_EXPECT;
4559 tcpcheck->string_len = 0;
4560 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004561 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4562 error = NULL;
4563 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4564 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4565 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4566 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
4569 }
4570 tcpcheck->inverse = inverse;
4571
4572 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4573 }
4574 else {
4575 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4576 file, linenum, args[0], args[1], ptr_arg);
4577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
4579 }
4580 }
4581 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004582 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004583 err_code |= ERR_ALERT | ERR_FATAL;
4584 goto out;
4585 }
4586 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004587 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004588 if (curproxy == &defproxy) {
4589 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004592 }
4593
Willy Tarreaub80c2302007-11-30 20:51:32 +01004594 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004596
4597 if (strcmp(args[1], "fail") == 0) {
4598 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004599 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004600 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4601 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004604 }
4605
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004606 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4607 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4608 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_ALERT | ERR_FATAL;
4610 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004611 }
4612 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4613 }
4614 else {
4615 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004618 }
4619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620#ifdef TPROXY
4621 else if (!strcmp(args[0], "transparent")) {
4622 /* enable transparent proxy connections */
4623 curproxy->options |= PR_O_TRANSP;
4624 }
4625#endif
4626 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004627 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004629
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 if (*(args[1]) == 0) {
4631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 }
4635 curproxy->maxconn = atol(args[1]);
4636 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004637 else if (!strcmp(args[0], "backlog")) { /* backlog */
4638 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004640
4641 if (*(args[1]) == 0) {
4642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004645 }
4646 curproxy->backlog = atol(args[1]);
4647 }
Willy Tarreau86034312006-12-29 00:10:33 +01004648 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004649 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004651
Willy Tarreau86034312006-12-29 00:10:33 +01004652 if (*(args[1]) == 0) {
4653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004656 }
4657 curproxy->fullconn = atol(args[1]);
4658 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4660 if (*(args[1]) == 0) {
4661 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004662 err_code |= ERR_ALERT | ERR_FATAL;
4663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004665 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4666 if (err) {
4667 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4668 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004671 }
4672 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 }
4674 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004675 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004676 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004677 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004678
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 if (curproxy == &defproxy) {
4680 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004684 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004685 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004686
Willy Tarreau902636f2013-03-10 19:44:48 +01004687 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004688 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004689 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004690 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004691 goto out;
4692 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004693
4694 proto = protocol_by_family(sk->ss_family);
4695 if (!proto || !proto->connect) {
4696 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4697 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
4701
4702 if (port1 != port2) {
4703 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4704 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004708
4709 if (!port1) {
4710 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4711 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004715
Willy Tarreaud5191e72010-02-09 20:50:45 +01004716 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004717 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 }
4719 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004721 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004722
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004723 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4724 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004729 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004730 /**
4731 * The syntax for hash-type config element is
4732 * hash-type {map-based|consistent} [[<algo>] avalanche]
4733 *
4734 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4735 */
4736 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004737
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004738 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4739 err_code |= ERR_WARN;
4740
4741 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004742 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4743 }
4744 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004745 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4746 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004747 else if (strcmp(args[1], "avalanche") == 0) {
4748 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]);
4749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004751 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004752 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004753 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
4756 }
Bhaskar98634f02013-10-29 23:30:51 -04004757
4758 /* set the hash function to use */
4759 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004760 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004761 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004762
4763 /* if consistent with no argument, then avalanche modifier is also applied */
4764 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4765 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004766 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004767 /* set the hash function */
4768 if (!strcmp(args[2], "sdbm")) {
4769 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4770 }
4771 else if (!strcmp(args[2], "djb2")) {
4772 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004773 } else if (!strcmp(args[2], "wt6")) {
4774 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004775 }
4776 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004777 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
4781
4782 /* set the hash modifier */
4783 if (!strcmp(args[3], "avalanche")) {
4784 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4785 }
4786 else if (*args[3]) {
4787 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
4790 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004791 }
William Lallemanda73203e2012-03-12 12:48:57 +01004792 }
William Lallemanda73203e2012-03-12 12:48:57 +01004793 else if (strcmp(args[0], "unique-id-format") == 0) {
4794 if (!*(args[1])) {
4795 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
4798 }
William Lallemand3203ff42012-11-11 17:30:56 +01004799 if (*(args[2])) {
4800 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004804 free(curproxy->conf.uniqueid_format_string);
4805 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004806
Willy Tarreau62a61232013-04-12 18:13:46 +02004807 free(curproxy->conf.uif_file);
4808 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4809 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004810 }
William Lallemanda73203e2012-03-12 12:48:57 +01004811
4812 else if (strcmp(args[0], "unique-id-header") == 0) {
4813 if (!*(args[1])) {
4814 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4815 err_code |= ERR_ALERT | ERR_FATAL;
4816 goto out;
4817 }
4818 free(curproxy->header_unique_id);
4819 curproxy->header_unique_id = strdup(args[1]);
4820 }
4821
William Lallemand723b73a2012-02-08 16:37:49 +01004822 else if (strcmp(args[0], "log-format") == 0) {
4823 if (!*(args[1])) {
4824 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
William Lallemand3203ff42012-11-11 17:30:56 +01004828 if (*(args[2])) {
4829 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
4832 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004833
Willy Tarreau62a61232013-04-12 18:13:46 +02004834 if (curproxy->conf.logformat_string != default_http_log_format &&
4835 curproxy->conf.logformat_string != default_tcp_log_format &&
4836 curproxy->conf.logformat_string != clf_http_log_format)
4837 free(curproxy->conf.logformat_string);
4838 curproxy->conf.logformat_string = strdup(args[1]);
4839
4840 free(curproxy->conf.lfs_file);
4841 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4842 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004843
4844 /* get a chance to improve log-format error reporting by
4845 * reporting the correct line-number when possible.
4846 */
4847 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4848 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4849 file, linenum, curproxy->id);
4850 err_code |= ERR_WARN;
4851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 }
William Lallemand723b73a2012-02-08 16:37:49 +01004853
William Lallemand0f99e342011-10-12 17:50:54 +02004854 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4855 /* delete previous herited or defined syslog servers */
4856 struct logsrv *back;
4857
4858 if (*(args[1]) != 0) {
4859 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863
William Lallemand723b73a2012-02-08 16:37:49 +01004864 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4865 LIST_DEL(&tmplogsrv->list);
4866 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004867 }
4868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004870 struct logsrv *logsrv;
4871
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004873 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004874 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004875 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004876 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004877 LIST_INIT(&node->list);
4878 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 }
4881 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004882 struct sockaddr_storage *sk;
4883 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004884 int arg = 0;
4885 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004886
4887 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004888
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004889 /* just after the address, a length may be specified */
4890 if (strcmp(args[arg+2], "len") == 0) {
4891 len = atoi(args[arg+3]);
4892 if (len < 80 || len > 65535) {
4893 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4894 file, linenum, args[arg+3]);
4895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
4897 }
4898 logsrv->maxlen = len;
4899
4900 /* skip these two args */
4901 arg += 2;
4902 }
4903 else
4904 logsrv->maxlen = MAX_SYSLOG_LEN;
4905
4906 if (logsrv->maxlen > global.max_syslog_len) {
4907 global.max_syslog_len = logsrv->maxlen;
4908 logline = realloc(logline, global.max_syslog_len + 1);
4909 }
4910
4911 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004912 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004913 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
4916
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
4918
William Lallemand0f99e342011-10-12 17:50:54 +02004919 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004920 if (*(args[arg+3])) {
4921 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004922 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004923 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
4926
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
4928 }
4929
William Lallemand0f99e342011-10-12 17:50:54 +02004930 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004931 if (*(args[arg+4])) {
4932 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004933 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004934 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
4937
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004938 }
4939 }
4940
Willy Tarreau902636f2013-03-10 19:44:48 +01004941 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004942 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004943 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004944 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004945 goto out;
4946 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004947
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004948 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004949
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004950 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004951 if (port1 != port2) {
4952 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4953 file, linenum, args[0], args[1]);
4954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
4956 }
4957
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004958 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004959 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
William Lallemand0f99e342011-10-12 17:50:54 +02004961
4962 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
4964 else {
4965 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4966 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_ALERT | ERR_FATAL;
4968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
4970 }
4971 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004972 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004973 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004974 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004975 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004976
Willy Tarreau977b8e42006-12-29 14:19:17 +01004977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004979
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004981 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4982 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004986
4987 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004988 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4989 free(curproxy->conn_src.iface_name);
4990 curproxy->conn_src.iface_name = NULL;
4991 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004992
Willy Tarreau902636f2013-03-10 19:44:48 +01004993 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004994 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004995 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004996 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004997 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004998 goto out;
4999 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005000
5001 proto = protocol_by_family(sk->ss_family);
5002 if (!proto || !proto->connect) {
5003 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005004 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
5007 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005008
5009 if (port1 != port2) {
5010 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5011 file, linenum, args[0], args[1]);
5012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
5014 }
5015
Willy Tarreauef9a3602012-12-08 22:29:20 +01005016 curproxy->conn_src.source_addr = *sk;
5017 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005018
5019 cur_arg = 2;
5020 while (*(args[cur_arg])) {
5021 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005022#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5023#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005024 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005025 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5026 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005029 }
5030#endif
5031 if (!*args[cur_arg + 1]) {
5032 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5033 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005036 }
5037
5038 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005039 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5040 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005041 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005042 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5043 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005044 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5045 char *name, *end;
5046
5047 name = args[cur_arg+1] + 7;
5048 while (isspace(*name))
5049 name++;
5050
5051 end = name;
5052 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5053 end++;
5054
Willy Tarreauef9a3602012-12-08 22:29:20 +01005055 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5056 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5057 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5058 curproxy->conn_src.bind_hdr_len = end - name;
5059 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5060 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5061 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005062
5063 /* now look for an occurrence number */
5064 while (isspace(*end))
5065 end++;
5066 if (*end == ',') {
5067 end++;
5068 name = end;
5069 if (*end == '-')
5070 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005071 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005072 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005073 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005074 }
5075
Willy Tarreauef9a3602012-12-08 22:29:20 +01005076 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005077 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5078 " occurrences values smaller than %d.\n",
5079 file, linenum, MAX_HDR_HISTORY);
5080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
5082 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005083 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005084 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005085
Willy Tarreau902636f2013-03-10 19:44:48 +01005086 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005087 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005088 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005089 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005090 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005091 goto out;
5092 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005093
5094 proto = protocol_by_family(sk->ss_family);
5095 if (!proto || !proto->connect) {
5096 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5097 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
5100 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005101
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005102 if (port1 != port2) {
5103 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5104 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
5107 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005108 curproxy->conn_src.tproxy_addr = *sk;
5109 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005110 }
5111 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005112#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005113 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005114#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005115#else /* no TPROXY support */
5116 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005117 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005120#endif
5121 cur_arg += 2;
5122 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005123 }
5124
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005125 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5126#ifdef SO_BINDTODEVICE
5127 if (!*args[cur_arg + 1]) {
5128 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5129 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005132 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005133 free(curproxy->conn_src.iface_name);
5134 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5135 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005136 global.last_checks |= LSTCHK_NETADM;
5137#else
5138 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5139 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005142#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005143 cur_arg += 2;
5144 continue;
5145 }
5146 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005147 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005152 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5153 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5154 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5161 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165
5166 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005167 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005168 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005169 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
5172 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005174 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005175 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
5179 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005181 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005182 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
5186 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005188 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005189 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
5193 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005195 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005196 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005200 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005202 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005203 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005205 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005206 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005207 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005209 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005210 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005212 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005213
5214 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5215 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005216 }
5217 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005219 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005220 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005222 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005223
5224 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5225 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5230 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234
5235 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005236 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005237 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 }
5241 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005243 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005244 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 }
5248 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005250 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005251 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
5255 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005257 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005258 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
5262 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005264 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005265 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005269 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005271 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005272 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005274 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005277 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005278
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 if (curproxy == &defproxy) {
5280 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005284 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 if (*(args[1]) == 0) {
5288 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005292
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005293 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005294 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5295 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5296 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
5299 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005300 err_code |= warnif_cond_conflicts(cond,
5301 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5302 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005303 }
5304 else if (*args[2]) {
5305 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5306 file, linenum, args[0], args[2]);
5307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
5310
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005311 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005312 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005313 wl->s = strdup(args[1]);
5314 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005315 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
5317 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005324
Willy Tarreauade5ec42010-01-28 19:33:49 +01005325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005326 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005327 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
5331 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005333 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005334 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 }
5338 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005340 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 }
5345 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005354 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005355 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
5359 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005361 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 }
5366 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005368 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
5373 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005374 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005375
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 if (curproxy == &defproxy) {
5377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005381 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005382 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383
Willy Tarreaubaaee002006-06-26 02:48:02 +02005384 if (*(args[1]) == 0) {
5385 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 }
5389
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005390 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005391 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5392 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5393 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005394 err_code |= ERR_ALERT | ERR_FATAL;
5395 goto out;
5396 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005397 err_code |= warnif_cond_conflicts(cond,
5398 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5399 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005400 }
5401 else if (*args[2]) {
5402 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5403 file, linenum, args[0], args[2]);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005408 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005409 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005410 wl->s = strdup(args[1]);
5411 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
5413 else if (!strcmp(args[0], "errorloc") ||
5414 !strcmp(args[0], "errorloc302") ||
5415 !strcmp(args[0], "errorloc303")) { /* error location */
5416 int errnum, errlen;
5417 char *err;
5418
Willy Tarreau977b8e42006-12-29 14:19:17 +01005419 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005420 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005421
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005423 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
5427
5428 errnum = atol(args[1]);
5429 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005430 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5431 err = malloc(errlen);
5432 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005434 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5435 err = malloc(errlen);
5436 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 }
5438
Willy Tarreau0f772532006-12-23 20:51:41 +01005439 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5440 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005441 chunk_destroy(&curproxy->errmsg[rc]);
5442 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005443 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005445 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005446
5447 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005448 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
5449 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 free(err);
5451 }
5452 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005453 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5454 int errnum, errlen, fd;
5455 char *err;
5456 struct stat stat;
5457
5458 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005460
5461 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005462 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005465 }
5466
5467 fd = open(args[2], O_RDONLY);
5468 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5469 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5470 file, linenum, args[2], args[1]);
5471 if (fd >= 0)
5472 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005475 }
5476
Willy Tarreau27a674e2009-08-17 07:23:33 +02005477 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005478 errlen = stat.st_size;
5479 } else {
5480 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005481 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005483 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005484 }
5485
5486 err = malloc(errlen); /* malloc() must succeed during parsing */
5487 errnum = read(fd, err, errlen);
5488 if (errnum != errlen) {
5489 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5490 file, linenum, args[2], args[1]);
5491 close(fd);
5492 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005495 }
5496 close(fd);
5497
5498 errnum = atol(args[1]);
5499 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5500 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005501 chunk_destroy(&curproxy->errmsg[rc]);
5502 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005503 break;
5504 }
5505 }
5506
5507 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005508 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
5509 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005510 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005511 free(err);
5512 }
5513 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005514 else if (!strcmp(args[0], "compression")) {
5515 struct comp *comp;
5516 if (curproxy->comp == NULL) {
5517 comp = calloc(1, sizeof(struct comp));
5518 curproxy->comp = comp;
5519 } else {
5520 comp = curproxy->comp;
5521 }
5522
5523 if (!strcmp(args[1], "algo")) {
5524 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005525 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005526
William Lallemand82fe75c2012-10-23 10:25:10 +02005527 cur_arg = 2;
5528 if (!*args[cur_arg]) {
5529 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5530 file, linenum, args[0]);
5531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 }
5534 while (*(args[cur_arg])) {
5535 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5536 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5537 file, linenum, args[0], args[cur_arg]);
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
William Lallemand552df672012-11-07 13:21:47 +01005541 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5542 curproxy->comp->algos->end(&ctx);
5543 } else {
5544 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5545 file, linenum, args[0], args[cur_arg]);
5546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005549 cur_arg ++;
5550 continue;
5551 }
5552 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005553 else if (!strcmp(args[1], "offload")) {
5554 comp->offload = 1;
5555 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005556 else if (!strcmp(args[1], "type")) {
5557 int cur_arg;
5558 cur_arg = 2;
5559 if (!*args[cur_arg]) {
5560 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5561 file, linenum, args[0]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565 while (*(args[cur_arg])) {
5566 comp_append_type(comp, args[cur_arg]);
5567 cur_arg ++;
5568 continue;
5569 }
5570 }
5571 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005572 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005573 file, linenum, args[0]);
5574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 }
5577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005579 struct cfg_kw_list *kwl;
5580 int index;
5581
5582 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5583 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5584 if (kwl->kw[index].section != CFG_LISTEN)
5585 continue;
5586 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5587 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005588 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005589 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005590 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005593 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005594 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005595 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_WARN;
5597 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005598 }
Willy Tarreau93893792009-07-23 13:19:11 +02005599 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005600 }
5601 }
5602 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005603
Willy Tarreau6daf3432008-01-22 16:44:08 +01005604 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 }
Willy Tarreau93893792009-07-23 13:19:11 +02005608 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005609 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005610 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611}
5612
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005613int
5614cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5615{
5616
5617 int err_code = 0;
5618 const char *err;
5619
5620 if (!strcmp(args[0], "userlist")) { /* new userlist */
5621 struct userlist *newul;
5622
5623 if (!*args[1]) {
5624 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5625 file, linenum, args[0]);
5626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
5629
5630 err = invalid_char(args[1]);
5631 if (err) {
5632 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5633 file, linenum, *err, args[0], args[1]);
5634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
5636 }
5637
5638 for (newul = userlist; newul; newul = newul->next)
5639 if (!strcmp(newul->name, args[1])) {
5640 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5641 file, linenum, args[1]);
5642 err_code |= ERR_WARN;
5643 goto out;
5644 }
5645
5646 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5647 if (!newul) {
5648 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5649 err_code |= ERR_ALERT | ERR_ABORT;
5650 goto out;
5651 }
5652
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005653 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005654 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005655 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5656 err_code |= ERR_ALERT | ERR_ABORT;
5657 goto out;
5658 }
5659
5660 newul->next = userlist;
5661 userlist = newul;
5662
5663 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005664 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005665 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005666 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005667
5668 if (!*args[1]) {
5669 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5670 file, linenum, args[0]);
5671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
5673 }
5674
5675 err = invalid_char(args[1]);
5676 if (err) {
5677 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5678 file, linenum, *err, args[0], args[1]);
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
5681 }
5682
William Lallemandfaf33152015-05-28 18:03:51 +02005683 if (!userlist)
5684 goto out;
5685
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005686 for (ag = userlist->groups; ag; ag = ag->next)
5687 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005688 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5689 file, linenum, args[1], userlist->name);
5690 err_code |= ERR_ALERT;
5691 goto out;
5692 }
5693
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005694 ag = calloc(1, sizeof(*ag));
5695 if (!ag) {
5696 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5697 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005698 goto out;
5699 }
5700
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005701 ag->name = strdup(args[1]);
5702 if (!ag) {
5703 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5704 err_code |= ERR_ALERT | ERR_ABORT;
5705 goto out;
5706 }
5707
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005708 cur_arg = 2;
5709
5710 while (*args[cur_arg]) {
5711 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005712 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005713 cur_arg += 2;
5714 continue;
5715 } else {
5716 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5717 file, linenum, args[0]);
5718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
5720 }
5721 }
5722
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005723 ag->next = userlist->groups;
5724 userlist->groups = ag;
5725
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005726 } else if (!strcmp(args[0], "user")) { /* new user */
5727 struct auth_users *newuser;
5728 int cur_arg;
5729
5730 if (!*args[1]) {
5731 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5732 file, linenum, args[0]);
5733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
5735 }
William Lallemandfaf33152015-05-28 18:03:51 +02005736 if (!userlist)
5737 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005738
5739 for (newuser = userlist->users; newuser; newuser = newuser->next)
5740 if (!strcmp(newuser->user, args[1])) {
5741 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5742 file, linenum, args[1], userlist->name);
5743 err_code |= ERR_ALERT;
5744 goto out;
5745 }
5746
5747 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5748 if (!newuser) {
5749 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5750 err_code |= ERR_ALERT | ERR_ABORT;
5751 goto out;
5752 }
5753
5754 newuser->user = strdup(args[1]);
5755
5756 newuser->next = userlist->users;
5757 userlist->users = newuser;
5758
5759 cur_arg = 2;
5760
5761 while (*args[cur_arg]) {
5762 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005763#ifdef CONFIG_HAP_CRYPT
5764 if (!crypt("", args[cur_arg + 1])) {
5765 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5766 file, linenum, newuser->user);
5767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
5769 }
5770#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005771 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5772 file, linenum);
5773 err_code |= ERR_ALERT;
5774#endif
5775 newuser->pass = strdup(args[cur_arg + 1]);
5776 cur_arg += 2;
5777 continue;
5778 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5779 newuser->pass = strdup(args[cur_arg + 1]);
5780 newuser->flags |= AU_O_INSECURE;
5781 cur_arg += 2;
5782 continue;
5783 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005784 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005785 cur_arg += 2;
5786 continue;
5787 } else {
5788 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5789 file, linenum, args[0]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
5793 }
5794 } else {
5795 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5796 err_code |= ERR_ALERT | ERR_FATAL;
5797 }
5798
5799out:
5800 return err_code;
5801}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802
5803/*
5804 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005805 * Returns the error code, 0 if OK, or any combination of :
5806 * - ERR_ABORT: must abort ASAP
5807 * - ERR_FATAL: we can continue parsing but not start the service
5808 * - ERR_WARN: a warning has been emitted
5809 * - ERR_ALERT: an alert has been emitted
5810 * Only the two first ones can stop processing, the two others are just
5811 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005813int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005815 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 FILE *f;
5817 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005818 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005819 struct cfg_section *cs = NULL;
5820 struct cfg_section *ics;
5821
5822 /* Register internal sections */
5823 if (!cfg_register_section("listen", cfg_parse_listen) ||
5824 !cfg_register_section("frontend", cfg_parse_listen) ||
5825 !cfg_register_section("backend", cfg_parse_listen) ||
5826 !cfg_register_section("ruleset", cfg_parse_listen) ||
5827 !cfg_register_section("defaults", cfg_parse_listen) ||
5828 !cfg_register_section("global", cfg_parse_global) ||
5829 !cfg_register_section("userlist", cfg_parse_users) ||
5830 !cfg_register_section("peers", cfg_parse_peers))
5831 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 if ((f=fopen(file,"r")) == NULL)
5834 return -1;
5835
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005836 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005837 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005838 char *end;
5839 char *args[MAX_LINE_ARGS + 1];
5840 char *line = thisline;
5841
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 linenum++;
5843
5844 end = line + strlen(line);
5845
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005846 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5847 /* Check if we reached the limit and the last char is not \n.
5848 * Watch out for the last line without the terminating '\n'!
5849 */
5850 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005851 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005852 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005853 }
5854
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005856 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 line++;
5858
5859 arg = 0;
5860 args[arg] = line;
5861
5862 while (*line && arg < MAX_LINE_ARGS) {
5863 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5864 * C equivalent value. Other combinations left unchanged (eg: \1).
5865 */
5866 if (*line == '\\') {
5867 int skip = 0;
5868 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5869 *line = line[1];
5870 skip = 1;
5871 }
5872 else if (line[1] == 'r') {
5873 *line = '\r';
5874 skip = 1;
5875 }
5876 else if (line[1] == 'n') {
5877 *line = '\n';
5878 skip = 1;
5879 }
5880 else if (line[1] == 't') {
5881 *line = '\t';
5882 skip = 1;
5883 }
5884 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005885 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 unsigned char hex1, hex2;
5887 hex1 = toupper(line[2]) - '0';
5888 hex2 = toupper(line[3]) - '0';
5889 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5890 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5891 *line = (hex1<<4) + hex2;
5892 skip = 3;
5893 }
5894 else {
5895 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005896 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 }
5898 }
5899 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005900 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 end -= skip;
5902 }
5903 line++;
5904 }
5905 else if (*line == '#' || *line == '\n' || *line == '\r') {
5906 /* end of string, end of loop */
5907 *line = 0;
5908 break;
5909 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005910 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005912 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005913 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 line++;
5915 args[++arg] = line;
5916 }
5917 else {
5918 line++;
5919 }
5920 }
5921
5922 /* empty line */
5923 if (!**args)
5924 continue;
5925
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005926 if (*line) {
5927 /* we had to stop due to too many args.
5928 * Let's terminate the string, print the offending part then cut the
5929 * last arg.
5930 */
5931 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5932 line++;
5933 *line = '\0';
5934
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005935 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005936 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005937 err_code |= ERR_ALERT | ERR_FATAL;
5938 args[arg] = line;
5939 }
5940
Willy Tarreau540abe42007-05-02 20:50:16 +02005941 /* zero out remaining args and ensure that at least one entry
5942 * is zeroed out.
5943 */
5944 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945 args[arg] = line;
5946 }
5947
Willy Tarreau3842f002009-06-14 11:39:52 +02005948 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005949 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005950 char *tmp;
5951
Willy Tarreau3842f002009-06-14 11:39:52 +02005952 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005953 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005954 for (arg=0; *args[arg+1]; arg++)
5955 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005956 *tmp = '\0'; // fix the next arg to \0
5957 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005958 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005959 else if (!strcmp(args[0], "default")) {
5960 kwm = KWM_DEF;
5961 for (arg=0; *args[arg+1]; arg++)
5962 args[arg] = args[arg+1]; // shift args after inversion
5963 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005964
William Lallemand0f99e342011-10-12 17:50:54 +02005965 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5966 strcmp(args[0], "log") != 0) {
5967 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005968 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005969 }
5970
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005971 /* detect section start */
5972 list_for_each_entry(ics, &sections, list) {
5973 if (strcmp(args[0], ics->section_name) == 0) {
5974 cursection = ics->section_name;
5975 cs = ics;
5976 break;
5977 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005978 }
5979
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005981 if (cs)
5982 err_code |= cs->section_parser(file, linenum, args, kwm);
5983 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005984 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005985 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005986 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005987
5988 if (err_code & ERR_ABORT)
5989 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005991 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005992 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005993 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005994}
5995
Willy Tarreau5436afc2014-09-16 12:17:36 +02005996/* This function propagates processes from frontend <from> to backend <to> so
5997 * that it is always guaranteed that a backend pointed to by a frontend is
5998 * bound to all of its processes. After that, if the target is a "listen"
5999 * instance, the function recursively descends the target's own targets along
6000 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6001 * checked first to ensure that <to> is already bound to all processes of
6002 * <from>, there is no risk of looping and we ensure to follow the shortest
6003 * path to the destination.
6004 *
6005 * It is possible to set <to> to NULL for the first call so that the function
6006 * takes care of visiting the initial frontend in <from>.
6007 *
6008 * It is important to note that the function relies on the fact that all names
6009 * have already been resolved.
6010 */
6011void propagate_processes(struct proxy *from, struct proxy *to)
6012{
6013 struct switching_rule *rule;
6014 struct hdr_exp *exp;
6015
6016 if (to) {
6017 /* check whether we need to go down */
6018 if (from->bind_proc &&
6019 (from->bind_proc & to->bind_proc) == from->bind_proc)
6020 return;
6021
6022 if (!from->bind_proc && !to->bind_proc)
6023 return;
6024
6025 to->bind_proc = from->bind_proc ?
6026 (to->bind_proc | from->bind_proc) : 0;
6027
6028 /* now propagate down */
6029 from = to;
6030 }
6031
Willy Tarreau7110f382014-12-18 13:56:26 +01006032 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006033 return;
6034
Willy Tarreaued061c02014-12-18 14:00:43 +01006035 if (from->state == PR_STSTOPPED)
6036 return;
6037
Willy Tarreau5436afc2014-09-16 12:17:36 +02006038 /* default_backend */
6039 if (from->defbe.be)
6040 propagate_processes(from, from->defbe.be);
6041
6042 /* use_backend */
6043 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006044 if (rule->dynamic)
6045 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006046 to = rule->be.backend;
6047 propagate_processes(from, to);
6048 }
6049
6050 /* reqsetbe */
6051 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6052 if (exp->action != ACT_SETBE)
6053 continue;
6054 to = (struct proxy *)exp->replace;
6055 propagate_processes(from, to);
6056 }
6057}
6058
Willy Tarreaubb925012009-07-23 13:36:36 +02006059/*
6060 * Returns the error code, 0 if OK, or any combination of :
6061 * - ERR_ABORT: must abort ASAP
6062 * - ERR_FATAL: we can continue parsing but not start the service
6063 * - ERR_WARN: a warning has been emitted
6064 * - ERR_ALERT: an alert has been emitted
6065 * Only the two first ones can stop processing, the two others are just
6066 * indicators.
6067 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006068int check_config_validity()
6069{
6070 int cfgerr = 0;
6071 struct proxy *curproxy = NULL;
6072 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006073 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006074 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006075 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006076
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006077 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078 /*
6079 * Now, check for the integrity of all that we have collected.
6080 */
6081
6082 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006083 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006084
Willy Tarreau193b8c62012-11-22 00:17:38 +01006085 if (!global.tune.max_http_hdr)
6086 global.tune.max_http_hdr = MAX_HTTP_HDR;
6087
6088 if (!global.tune.cookie_len)
6089 global.tune.cookie_len = CAPTURE_LEN;
6090
6091 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6092
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006093 /* Post initialisation of the users and groups lists. */
6094 err_code = userlist_postinit();
6095 if (err_code != ERR_NONE)
6096 goto out;
6097
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006098 /* first, we will invert the proxy list order */
6099 curproxy = NULL;
6100 while (proxy) {
6101 struct proxy *next;
6102
6103 next = proxy->next;
6104 proxy->next = curproxy;
6105 curproxy = proxy;
6106 if (!next)
6107 break;
6108 proxy = next;
6109 }
6110
Willy Tarreau91b00c22014-09-16 13:41:21 +02006111 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006112 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006113 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006114 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006115 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006116 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006117 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006118
Willy Tarreau050536d2012-10-04 08:47:34 +02006119 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006120 /* proxy ID not set, use automatic numbering with first
6121 * spare entry starting with next_pxid.
6122 */
6123 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6124 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6125 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006126 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006127 next_pxid++;
6128
Willy Tarreau55ea7572007-06-17 19:56:27 +02006129
Willy Tarreaubaaee002006-06-26 02:48:02 +02006130 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006131 /* ensure we don't keep listeners uselessly bound */
6132 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006133 free((void *)curproxy->table.peers.name);
6134 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 continue;
6136 }
6137
Willy Tarreau102df612014-05-07 23:56:38 +02006138 /* Check multi-process mode compatibility for the current proxy */
6139
6140 if (curproxy->bind_proc) {
6141 /* an explicit bind-process was specified, let's check how many
6142 * processes remain.
6143 */
David Carlier6de4c2f2015-07-02 07:00:17 +00006144 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02006145
6146 curproxy->bind_proc &= nbits(global.nbproc);
6147 if (!curproxy->bind_proc && nbproc == 1) {
6148 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);
6149 curproxy->bind_proc = 1;
6150 }
6151 else if (!curproxy->bind_proc && nbproc > 1) {
6152 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);
6153 curproxy->bind_proc = 0;
6154 }
6155 }
6156
Willy Tarreau3d209582014-05-09 17:06:11 +02006157 /* check and reduce the bind-proc of each listener */
6158 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6159 unsigned long mask;
6160
6161 if (!bind_conf->bind_proc)
6162 continue;
6163
6164 mask = nbits(global.nbproc);
6165 if (curproxy->bind_proc)
6166 mask &= curproxy->bind_proc;
6167 /* mask cannot be null here thanks to the previous checks */
6168
David Carlier6de4c2f2015-07-02 07:00:17 +00006169 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02006170 bind_conf->bind_proc &= mask;
6171
6172 if (!bind_conf->bind_proc && nbproc == 1) {
6173 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",
6174 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6175 bind_conf->bind_proc = mask & ~(mask - 1);
6176 }
6177 else if (!bind_conf->bind_proc && nbproc > 1) {
6178 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",
6179 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6180 bind_conf->bind_proc = 0;
6181 }
6182 }
6183
Willy Tarreauff01a212009-03-15 13:46:16 +01006184 switch (curproxy->mode) {
6185 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006186 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006187 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006188 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6189 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006190 cfgerr++;
6191 }
6192
6193 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006194 Warning("config : servers will be ignored for %s '%s'.\n",
6195 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006196 break;
6197
6198 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006199 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006200 break;
6201
6202 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006203 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006204 break;
6205 }
6206
Willy Tarreauc7c1e552015-08-11 11:36:45 +02006207 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
6208 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
6209 proxy_type_str(curproxy), curproxy->id);
6210 err_code |= ERR_WARN;
6211 }
6212
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006213 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006214 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006215 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006216 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6217 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006218 cfgerr++;
6219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006220#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006221 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006222 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6223 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006224 cfgerr++;
6225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006226#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006227 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006228 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6229 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006230 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006231 }
6232 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006233 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006234 /* If no LB algo is set in a backend, and we're not in
6235 * transparent mode, dispatch mode nor proxy mode, we
6236 * want to use balance roundrobin by default.
6237 */
6238 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6239 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006240 }
6241 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006242
Willy Tarreau1620ec32011-08-06 17:05:02 +02006243 if (curproxy->options & PR_O_DISPATCH)
6244 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6245 else if (curproxy->options & PR_O_HTTP_PROXY)
6246 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6247 else if (curproxy->options & PR_O_TRANSP)
6248 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006249
Willy Tarreau1620ec32011-08-06 17:05:02 +02006250 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6251 if (curproxy->options & PR_O_DISABLE404) {
6252 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6253 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6254 err_code |= ERR_WARN;
6255 curproxy->options &= ~PR_O_DISABLE404;
6256 }
6257 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6258 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6259 "send-state", proxy_type_str(curproxy), curproxy->id);
6260 err_code |= ERR_WARN;
6261 curproxy->options &= ~PR_O2_CHK_SNDST;
6262 }
Willy Tarreauef781042010-01-27 11:53:01 +01006263 }
6264
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006265 /* if a default backend was specified, let's find it */
6266 if (curproxy->defbe.name) {
6267 struct proxy *target;
6268
Alex Williams96532db2009-11-01 21:27:13 -05006269 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006270 if (!target) {
6271 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6272 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006273 cfgerr++;
6274 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006275 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6276 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006277 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006278 } else {
6279 free(curproxy->defbe.name);
6280 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006281
6282 /* Emit a warning if this proxy also has some servers */
6283 if (curproxy->srv) {
6284 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6285 curproxy->id);
6286 err_code |= ERR_WARN;
6287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006288 }
6289 }
6290
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006291 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006292 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6293 /* map jump target for ACT_SETBE in req_rep chain */
6294 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006295 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006296 struct proxy *target;
6297
Willy Tarreaua496b602006-12-17 23:15:24 +01006298 if (exp->action != ACT_SETBE)
6299 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006300
Alex Williams96532db2009-11-01 21:27:13 -05006301 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006302 if (!target) {
6303 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6304 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006305 cfgerr++;
6306 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006307 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6308 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006309 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006310 } else {
6311 free((void *)exp->replace);
6312 exp->replace = (const char *)target;
6313 }
6314 }
6315 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006316
6317 /* find the target proxy for 'use_backend' rules */
6318 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006319 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006320 struct logformat_node *node;
6321 char *pxname;
6322
6323 /* Try to parse the string as a log format expression. If the result
6324 * of the parsing is only one entry containing a simple string, then
6325 * it's a standard string corresponding to a static rule, thus the
6326 * parsing is cancelled and be.name is restored to be resolved.
6327 */
6328 pxname = rule->be.name;
6329 LIST_INIT(&rule->be.expr);
6330 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6331 curproxy->conf.args.file, curproxy->conf.args.line);
6332 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6333
6334 if (!LIST_ISEMPTY(&rule->be.expr)) {
6335 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6336 rule->dynamic = 1;
6337 free(pxname);
6338 continue;
6339 }
6340 /* simple string: free the expression and fall back to static rule */
6341 free(node->arg);
6342 free(node);
6343 }
6344
6345 rule->dynamic = 0;
6346 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006347
Alex Williams96532db2009-11-01 21:27:13 -05006348 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006349
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006350 if (!target) {
6351 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6352 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006353 cfgerr++;
6354 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006355 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6356 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006357 cfgerr++;
6358 } else {
6359 free((void *)rule->be.name);
6360 rule->be.backend = target;
6361 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006362 }
6363
Willy Tarreau5436afc2014-09-16 12:17:36 +02006364 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006365 list_for_each_entry(srule, &curproxy->server_rules, list) {
6366 struct server *target = findserver(curproxy, srule->srv.name);
6367
6368 if (!target) {
6369 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6370 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6371 cfgerr++;
6372 continue;
6373 }
6374 free((void *)srule->srv.name);
6375 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006376 }
6377
Emeric Brunb982a3d2010-01-04 15:45:53 +01006378 /* find the target table for 'stick' rules */
6379 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6380 struct proxy *target;
6381
Emeric Brun1d33b292010-01-04 15:47:17 +01006382 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6383 if (mrule->flags & STK_IS_STORE)
6384 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6385
Emeric Brunb982a3d2010-01-04 15:45:53 +01006386 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006387 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006388 else
6389 target = curproxy;
6390
6391 if (!target) {
6392 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6393 curproxy->id, mrule->table.name);
6394 cfgerr++;
6395 }
6396 else if (target->table.size == 0) {
6397 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6398 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6399 cfgerr++;
6400 }
Willy Tarreau12785782012-04-27 21:37:17 +02006401 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6402 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006403 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6404 cfgerr++;
6405 }
6406 else {
6407 free((void *)mrule->table.name);
6408 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006409 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006410 }
6411 }
6412
6413 /* find the target table for 'store response' rules */
6414 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6415 struct proxy *target;
6416
Emeric Brun1d33b292010-01-04 15:47:17 +01006417 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6418
Emeric Brunb982a3d2010-01-04 15:45:53 +01006419 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006420 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006421 else
6422 target = curproxy;
6423
6424 if (!target) {
6425 Alert("Proxy '%s': unable to find store table '%s'.\n",
6426 curproxy->id, mrule->table.name);
6427 cfgerr++;
6428 }
6429 else if (target->table.size == 0) {
6430 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6431 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6432 cfgerr++;
6433 }
Willy Tarreau12785782012-04-27 21:37:17 +02006434 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6435 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006436 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6437 cfgerr++;
6438 }
6439 else {
6440 free((void *)mrule->table.name);
6441 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006442 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006443 }
6444 }
6445
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006446 /* find the target table for 'tcp-request' layer 4 rules */
6447 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6448 struct proxy *target;
6449
Willy Tarreaub4c84932013-07-23 19:15:30 +02006450 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006451 continue;
6452
6453 if (trule->act_prm.trk_ctr.table.n)
6454 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6455 else
6456 target = curproxy;
6457
6458 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006459 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6460 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006461 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006462 cfgerr++;
6463 }
6464 else if (target->table.size == 0) {
6465 Alert("Proxy '%s': table '%s' used but not configured.\n",
6466 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6467 cfgerr++;
6468 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006469 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6470 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6471 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006472 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006473 cfgerr++;
6474 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006475 else {
6476 free(trule->act_prm.trk_ctr.table.n);
6477 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006478 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006479 * to pass a list of counters to track and allocate them right here using
6480 * stktable_alloc_data_type().
6481 */
6482 }
6483 }
6484
Willy Tarreaud1f96522010-08-03 19:34:32 +02006485 /* find the target table for 'tcp-request' layer 6 rules */
6486 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6487 struct proxy *target;
6488
Willy Tarreaub4c84932013-07-23 19:15:30 +02006489 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006490 continue;
6491
6492 if (trule->act_prm.trk_ctr.table.n)
6493 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6494 else
6495 target = curproxy;
6496
6497 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006498 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6499 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006500 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006501 cfgerr++;
6502 }
6503 else if (target->table.size == 0) {
6504 Alert("Proxy '%s': table '%s' used but not configured.\n",
6505 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6506 cfgerr++;
6507 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006508 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6509 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6510 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006511 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006512 cfgerr++;
6513 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006514 else {
6515 free(trule->act_prm.trk_ctr.table.n);
6516 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006517 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006518 * to pass a list of counters to track and allocate them right here using
6519 * stktable_alloc_data_type().
6520 */
6521 }
6522 }
6523
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006524 /* move any "block" rules at the beginning of the http-request rules */
6525 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6526 /* insert block_rules into http_req_rules at the beginning */
6527 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6528 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6529 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6530 curproxy->http_req_rules.n = curproxy->block_rules.n;
6531 LIST_INIT(&curproxy->block_rules);
6532 }
6533
Emeric Brun32da3c42010-09-23 18:39:19 +02006534 if (curproxy->table.peers.name) {
6535 struct peers *curpeers = peers;
6536
6537 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6538 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6539 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006540 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006541 break;
6542 }
6543 }
6544
6545 if (!curpeers) {
6546 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6547 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006548 free((void *)curproxy->table.peers.name);
6549 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006550 cfgerr++;
6551 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006552 else if (curpeers->state == PR_STSTOPPED) {
6553 /* silently disable this peers section */
6554 curproxy->table.peers.p = NULL;
6555 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006556 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006557 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6558 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006559 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006560 cfgerr++;
6561 }
6562 }
6563
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006564 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006565 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006566 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6567 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6568 "proxy", curproxy->id);
6569 cfgerr++;
6570 goto out_uri_auth_compat;
6571 }
6572
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006573 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006574 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006575 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006576 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006577
Willy Tarreau95fa4692010-02-01 13:05:50 +01006578 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6579 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006580
6581 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006582 uri_auth_compat_req[i++] = "realm";
6583 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6584 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006585
Willy Tarreau95fa4692010-02-01 13:05:50 +01006586 uri_auth_compat_req[i++] = "unless";
6587 uri_auth_compat_req[i++] = "{";
6588 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6589 uri_auth_compat_req[i++] = "}";
6590 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006591
Willy Tarreauff011f22011-01-06 17:51:27 +01006592 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6593 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006594 cfgerr++;
6595 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006596 }
6597
Willy Tarreauff011f22011-01-06 17:51:27 +01006598 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006599
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006600 if (curproxy->uri_auth->auth_realm) {
6601 free(curproxy->uri_auth->auth_realm);
6602 curproxy->uri_auth->auth_realm = NULL;
6603 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006604
6605 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006606 }
6607out_uri_auth_compat:
6608
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006609 /* compile the log format */
6610 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006611 if (curproxy->conf.logformat_string != default_http_log_format &&
6612 curproxy->conf.logformat_string != default_tcp_log_format &&
6613 curproxy->conf.logformat_string != clf_http_log_format)
6614 free(curproxy->conf.logformat_string);
6615 curproxy->conf.logformat_string = NULL;
6616 free(curproxy->conf.lfs_file);
6617 curproxy->conf.lfs_file = NULL;
6618 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006619 }
6620
Willy Tarreau62a61232013-04-12 18:13:46 +02006621 if (curproxy->conf.logformat_string) {
6622 curproxy->conf.args.ctx = ARGC_LOG;
6623 curproxy->conf.args.file = curproxy->conf.lfs_file;
6624 curproxy->conf.args.line = curproxy->conf.lfs_line;
6625 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006626 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006627 curproxy->conf.args.file = NULL;
6628 curproxy->conf.args.line = 0;
6629 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006630
Willy Tarreau62a61232013-04-12 18:13:46 +02006631 if (curproxy->conf.uniqueid_format_string) {
6632 curproxy->conf.args.ctx = ARGC_UIF;
6633 curproxy->conf.args.file = curproxy->conf.uif_file;
6634 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006635 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006636 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006637 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006638 curproxy->conf.args.file = NULL;
6639 curproxy->conf.args.line = 0;
6640 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006641
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006642 /* only now we can check if some args remain unresolved.
6643 * This must be done after the users and groups resolution.
6644 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006645 cfgerr += smp_resolve_args(curproxy);
6646 if (!cfgerr)
6647 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006648
Willy Tarreau2738a142006-07-08 17:28:09 +02006649 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006650 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006651 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006652 (!curproxy->timeout.connect ||
6653 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006654 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006655 " | While not properly invalid, you will certainly encounter various problems\n"
6656 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006657 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006658 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006659 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006660 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006661
Willy Tarreau1fa31262007-12-03 00:36:16 +01006662 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6663 * We must still support older configurations, so let's find out whether those
6664 * parameters have been set or must be copied from contimeouts.
6665 */
6666 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006667 if (!curproxy->timeout.tarpit ||
6668 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006669 /* tarpit timeout not set. We search in the following order:
6670 * default.tarpit, curr.connect, default.connect.
6671 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006672 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006673 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006674 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006675 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006676 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006677 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006678 }
6679 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006680 (!curproxy->timeout.queue ||
6681 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006682 /* queue timeout not set. We search in the following order:
6683 * default.queue, curr.connect, default.connect.
6684 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006685 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006686 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006687 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006688 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006689 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006690 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006691 }
6692 }
6693
Willy Tarreau1620ec32011-08-06 17:05:02 +02006694 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006695 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6696 curproxy->check_req = (char *)malloc(curproxy->check_len);
6697 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006698 }
6699
Willy Tarreau215663d2014-06-13 18:30:23 +02006700 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6701 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6702 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6703 proxy_type_str(curproxy), curproxy->id);
6704 err_code |= ERR_WARN;
6705 }
6706
Willy Tarreau193b8c62012-11-22 00:17:38 +01006707 /* ensure that cookie capture length is not too large */
6708 if (curproxy->capture_len >= global.tune.cookie_len) {
6709 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6710 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6711 err_code |= ERR_WARN;
6712 curproxy->capture_len = global.tune.cookie_len - 1;
6713 }
6714
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006715 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006716 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006717 curproxy->req_cap_pool = create_pool("ptrcap",
6718 curproxy->nb_req_cap * sizeof(char *),
6719 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006720 }
6721
6722 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006723 curproxy->rsp_cap_pool = create_pool("ptrcap",
6724 curproxy->nb_rsp_cap * sizeof(char *),
6725 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006726 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006727
Willy Tarreaubaaee002006-06-26 02:48:02 +02006728 /* first, we will invert the servers list order */
6729 newsrv = NULL;
6730 while (curproxy->srv) {
6731 struct server *next;
6732
6733 next = curproxy->srv->next;
6734 curproxy->srv->next = newsrv;
6735 newsrv = curproxy->srv;
6736 if (!next)
6737 break;
6738 curproxy->srv = next;
6739 }
6740
Willy Tarreau17edc812014-01-03 12:14:34 +01006741 /* Check that no server name conflicts. This causes trouble in the stats.
6742 * We only emit a warning for the first conflict affecting each server,
6743 * in order to avoid combinatory explosion if all servers have the same
6744 * name. We do that only for servers which do not have an explicit ID,
6745 * because these IDs were made also for distinguishing them and we don't
6746 * want to annoy people who correctly manage them.
6747 */
6748 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6749 struct server *other_srv;
6750
6751 if (newsrv->puid)
6752 continue;
6753
6754 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6755 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6756 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6757 newsrv->conf.file, newsrv->conf.line,
6758 proxy_type_str(curproxy), curproxy->id,
6759 newsrv->id, other_srv->conf.line);
6760 break;
6761 }
6762 }
6763 }
6764
Willy Tarreaudd701652010-05-25 23:03:02 +02006765 /* assign automatic UIDs to servers which don't have one yet */
6766 next_id = 1;
6767 newsrv = curproxy->srv;
6768 while (newsrv != NULL) {
6769 if (!newsrv->puid) {
6770 /* server ID not set, use automatic numbering with first
6771 * spare entry starting with next_svid.
6772 */
6773 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6774 newsrv->conf.id.key = newsrv->puid = next_id;
6775 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6776 }
6777 next_id++;
6778 newsrv = newsrv->next;
6779 }
6780
Willy Tarreau20697042007-11-15 23:26:18 +01006781 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006782 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006783
Willy Tarreau62c3be22012-01-20 13:12:32 +01006784 /*
6785 * If this server supports a maxconn parameter, it needs a dedicated
6786 * tasks to fill the emptied slots when a connection leaves.
6787 * Also, resolve deferred tracking dependency if needed.
6788 */
6789 newsrv = curproxy->srv;
6790 while (newsrv != NULL) {
6791 if (newsrv->minconn > newsrv->maxconn) {
6792 /* Only 'minconn' was specified, or it was higher than or equal
6793 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6794 * this will avoid further useless expensive computations.
6795 */
6796 newsrv->maxconn = newsrv->minconn;
6797 } else if (newsrv->maxconn && !newsrv->minconn) {
6798 /* minconn was not specified, so we set it to maxconn */
6799 newsrv->minconn = newsrv->maxconn;
6800 }
6801
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006802#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006803 if (newsrv->use_ssl || newsrv->check.use_ssl)
6804 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006805#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006806
Willy Tarreau2f075e92013-12-03 11:11:34 +01006807 /* set the check type on the server */
6808 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6809
Willy Tarreau62c3be22012-01-20 13:12:32 +01006810 if (newsrv->trackit) {
6811 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006812 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006813 char *pname, *sname;
6814
6815 pname = newsrv->trackit;
6816 sname = strrchr(pname, '/');
6817
6818 if (sname)
6819 *sname++ = '\0';
6820 else {
6821 sname = pname;
6822 pname = NULL;
6823 }
6824
6825 if (pname) {
6826 px = findproxy(pname, PR_CAP_BE);
6827 if (!px) {
6828 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6829 proxy_type_str(curproxy), curproxy->id,
6830 newsrv->id, pname);
6831 cfgerr++;
6832 goto next_srv;
6833 }
6834 } else
6835 px = curproxy;
6836
6837 srv = findserver(px, sname);
6838 if (!srv) {
6839 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6840 proxy_type_str(curproxy), curproxy->id,
6841 newsrv->id, sname);
6842 cfgerr++;
6843 goto next_srv;
6844 }
6845
Willy Tarreau32091232014-05-16 13:52:00 +02006846 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6847 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6848 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006849 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006850 "tracking as it does not have any check nor agent enabled.\n",
6851 proxy_type_str(curproxy), curproxy->id,
6852 newsrv->id, px->id, srv->id);
6853 cfgerr++;
6854 goto next_srv;
6855 }
6856
6857 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6858
6859 if (loop) {
6860 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6861 "belongs to a tracking chain looping back to %s/%s.\n",
6862 proxy_type_str(curproxy), curproxy->id,
6863 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006864 cfgerr++;
6865 goto next_srv;
6866 }
6867
6868 if (curproxy != px &&
6869 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6870 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6871 "tracking: disable-on-404 option inconsistency.\n",
6872 proxy_type_str(curproxy), curproxy->id,
6873 newsrv->id, px->id, srv->id);
6874 cfgerr++;
6875 goto next_srv;
6876 }
6877
6878 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006879 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006880 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006881 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006882 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006883 }
6884
6885 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006886 newsrv->tracknext = srv->trackers;
6887 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006888
6889 free(newsrv->trackit);
6890 newsrv->trackit = NULL;
6891 }
6892 next_srv:
6893 newsrv = newsrv->next;
6894 }
6895
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006896 /* We have to initialize the server lookup mechanism depending
6897 * on what LB algorithm was choosen.
6898 */
6899
6900 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6901 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6902 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006903 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6904 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6905 init_server_map(curproxy);
6906 } else {
6907 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6908 fwrr_init_server_groups(curproxy);
6909 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006910 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006911
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006912 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006913 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6914 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6915 fwlc_init_server_tree(curproxy);
6916 } else {
6917 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6918 fas_init_server_tree(curproxy);
6919 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006920 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006921
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006922 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006923 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6924 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6925 chash_init_server_tree(curproxy);
6926 } else {
6927 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6928 init_server_map(curproxy);
6929 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006930 break;
6931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006932
6933 if (curproxy->options & PR_O_LOGASAP)
6934 curproxy->to_log &= ~LW_BYTES;
6935
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006936 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006937 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006938 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6939 proxy_type_str(curproxy), curproxy->id);
6940 err_code |= ERR_WARN;
6941 }
6942
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006943 if (curproxy->mode != PR_MODE_HTTP) {
6944 int optnum;
6945
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006946 if (curproxy->uri_auth) {
6947 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6948 proxy_type_str(curproxy), curproxy->id);
6949 err_code |= ERR_WARN;
6950 curproxy->uri_auth = NULL;
6951 }
6952
Willy Tarreau87cf5142011-08-19 22:57:24 +02006953 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006954 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6955 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6956 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006957 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006958 }
6959
6960 if (curproxy->options & PR_O_ORGTO) {
6961 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6962 "originalto", proxy_type_str(curproxy), curproxy->id);
6963 err_code |= ERR_WARN;
6964 curproxy->options &= ~PR_O_ORGTO;
6965 }
6966
6967 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6968 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6969 (curproxy->cap & cfg_opts[optnum].cap) &&
6970 (curproxy->options & cfg_opts[optnum].val)) {
6971 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6972 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6973 err_code |= ERR_WARN;
6974 curproxy->options &= ~cfg_opts[optnum].val;
6975 }
6976 }
6977
6978 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6979 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6980 (curproxy->cap & cfg_opts2[optnum].cap) &&
6981 (curproxy->options2 & cfg_opts2[optnum].val)) {
6982 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6983 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6984 err_code |= ERR_WARN;
6985 curproxy->options2 &= ~cfg_opts2[optnum].val;
6986 }
6987 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006988
Pieter Baauwd551fb52013-05-08 22:49:23 +02006989#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006990 if (curproxy->conn_src.bind_hdr_occ) {
6991 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006992 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006993 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006994 err_code |= ERR_WARN;
6995 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006996#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006997 }
6998
Willy Tarreaubaaee002006-06-26 02:48:02 +02006999 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007000 * ensure that we're not cross-dressing a TCP server into HTTP.
7001 */
7002 newsrv = curproxy->srv;
7003 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007004 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007005 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7006 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007007 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007008 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007009
Willy Tarreau0cec3312011-10-31 13:49:26 +01007010 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7011 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7012 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7013 err_code |= ERR_WARN;
7014 }
7015
Willy Tarreauc93cd162014-05-13 15:54:22 +02007016 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007017 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7018 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7019 err_code |= ERR_WARN;
7020 }
7021
Pieter Baauwd551fb52013-05-08 22:49:23 +02007022#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007023 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7024 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007025 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 +01007026 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007027 err_code |= ERR_WARN;
7028 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007029#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007030 newsrv = newsrv->next;
7031 }
7032
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007033 /* check if we have a frontend with "tcp-request content" looking at L7
7034 * with no inspect-delay
7035 */
7036 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7037 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7038 if (trule->action == TCP_ACT_CAPTURE &&
7039 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7040 break;
7041 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7042 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7043 break;
7044 }
7045
7046 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7047 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7048 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7049 " This means that these rules will randomly find their contents. This can be fixed by"
7050 " setting the tcp-request inspect-delay.\n",
7051 proxy_type_str(curproxy), curproxy->id);
7052 err_code |= ERR_WARN;
7053 }
7054 }
7055
Willy Tarreauc1a21672009-08-16 22:37:44 +02007056 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007057 if (!curproxy->accept)
7058 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007059
Willy Tarreauc1a21672009-08-16 22:37:44 +02007060 if (curproxy->tcp_req.inspect_delay ||
7061 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007062 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007063
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007064 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007065 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007066 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007067 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007068
7069 /* both TCP and HTTP must check switching rules */
7070 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7071 }
7072
7073 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007074 if (curproxy->tcp_req.inspect_delay ||
7075 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7076 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7077
Emeric Brun97679e72010-09-23 17:56:44 +02007078 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7079 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7080
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007081 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007082 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007083 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007084 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007085
7086 /* If the backend does requires RDP cookie persistence, we have to
7087 * enable the corresponding analyser.
7088 */
7089 if (curproxy->options2 & PR_O2_RDPC_PRST)
7090 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7091 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007092 }
7093
7094 /***********************************************************/
7095 /* At this point, target names have already been resolved. */
7096 /***********************************************************/
7097
7098 /* Check multi-process mode compatibility */
7099
7100 if (global.nbproc > 1 && global.stats_fe) {
7101 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7102 unsigned long mask;
7103
7104 mask = nbits(global.nbproc);
7105 if (global.stats_fe->bind_proc)
7106 mask &= global.stats_fe->bind_proc;
7107
7108 if (bind_conf->bind_proc)
7109 mask &= bind_conf->bind_proc;
7110
7111 /* stop here if more than one process is used */
David Carlier6de4c2f2015-07-02 07:00:17 +00007112 if (my_popcountl(mask) > 1)
Willy Tarreau91b00c22014-09-16 13:41:21 +02007113 break;
7114 }
7115 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7116 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");
7117 }
7118 }
7119
7120 /* Make each frontend inherit bind-process from its listeners when not specified. */
7121 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7122 if (curproxy->bind_proc)
7123 continue;
7124
7125 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7126 unsigned long mask;
7127
Willy Tarreau01760ad2015-05-04 21:57:58 +02007128 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007129 curproxy->bind_proc |= mask;
7130 }
7131
7132 if (!curproxy->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007133 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007134 }
7135
7136 if (global.stats_fe) {
7137 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7138 unsigned long mask;
7139
Cyril Bonté32e4f252016-02-24 00:14:54 +01007140 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau91b00c22014-09-16 13:41:21 +02007141 global.stats_fe->bind_proc |= mask;
7142 }
7143 if (!global.stats_fe->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007144 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007145 }
7146
Willy Tarreaub3228c82014-10-01 20:50:17 +02007147 /* propagate bindings from frontends to backends. Don't do it if there
7148 * are any fatal errors as we must not call it with unresolved proxies.
7149 */
7150 if (!cfgerr) {
7151 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7152 if (curproxy->cap & PR_CAP_FE)
7153 propagate_processes(curproxy, NULL);
7154 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007155 }
7156
7157 /* Bind each unbound backend to all processes when not specified. */
7158 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7159 if (curproxy->bind_proc)
7160 continue;
Willy Tarreau01760ad2015-05-04 21:57:58 +02007161 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007162 }
7163
7164 /*******************************************************/
7165 /* At this step, all proxies have a non-null bind_proc */
7166 /*******************************************************/
7167
7168 /* perform the final checks before creating tasks */
7169
7170 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7171 struct listener *listener;
7172 unsigned int next_id;
7173 int nbproc;
7174
David Carlier6de4c2f2015-07-02 07:00:17 +00007175 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007176
Emeric Brunc52962f2012-11-15 18:28:02 +01007177#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007178 /* Configure SSL for each bind line.
7179 * Note: if configuration fails at some point, the ->ctx member
7180 * remains NULL so that listeners can later detach.
7181 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007182 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007183 int alloc_ctx;
7184
Emeric Brunc52962f2012-11-15 18:28:02 +01007185 if (!bind_conf->is_ssl) {
7186 if (bind_conf->default_ctx) {
7187 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7188 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7189 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007190 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007191 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007192 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007193 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007194 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007195 cfgerr++;
7196 continue;
7197 }
7198
Emeric Brun8dc60392014-05-09 13:52:00 +02007199 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007200 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007201 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7202 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");
7203 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007204 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007205 cfgerr++;
7206 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007207 }
7208
Emeric Brunfc0421f2012-09-07 17:30:07 +02007209 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007210 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007211 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007212#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007213
Willy Tarreaue6b98942007-10-29 01:09:36 +01007214 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007215 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007216 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007217 if (!listener->luid) {
7218 /* listener ID not set, use automatic numbering with first
7219 * spare entry starting with next_luid.
7220 */
7221 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7222 listener->conf.id.key = listener->luid = next_id;
7223 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007224 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007225 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007226
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007227 /* enable separate counters */
7228 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7229 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007230 if (!listener->name)
7231 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007232 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007233
Willy Tarreaue6b98942007-10-29 01:09:36 +01007234 if (curproxy->options & PR_O_TCP_NOLING)
7235 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007236 if (!listener->maxconn)
7237 listener->maxconn = curproxy->maxconn;
7238 if (!listener->backlog)
7239 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007240 if (!listener->maxaccept)
7241 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7242
7243 /* we want to have an optimal behaviour on single process mode to
7244 * maximize the work at once, but in multi-process we want to keep
7245 * some fairness between processes, so we target half of the max
7246 * number of events to be balanced over all the processes the proxy
7247 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7248 * used to disable the limit.
7249 */
7250 if (listener->maxaccept > 0) {
7251 if (nbproc > 1)
7252 listener->maxaccept = (listener->maxaccept + 1) / 2;
7253 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7254 }
7255
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007256 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007257 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007258 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007259 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007260
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007261 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7262 listener->options |= LI_O_TCP_RULES;
7263
Willy Tarreaude3041d2010-05-31 10:56:17 +02007264 if (curproxy->mon_mask.s_addr)
7265 listener->options |= LI_O_CHK_MONNET;
7266
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007267 /* smart accept mode is automatic in HTTP mode */
7268 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007269 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007270 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7271 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007272 }
7273
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007274 /* Release unused SSL configs */
7275 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7276 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007277 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007278#ifdef USE_OPENSSL
7279 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007280 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007281 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007282 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007283 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007284#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007285 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007286
Willy Tarreau102df612014-05-07 23:56:38 +02007287 if (nbproc > 1) {
7288 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007289 int count, maxproc = 0;
7290
7291 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carlier6de4c2f2015-07-02 07:00:17 +00007292 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreau036a83e2014-09-16 15:11:04 +02007293 if (count > maxproc)
7294 maxproc = count;
7295 }
7296 /* backends have 0, frontends have 1 or more */
7297 if (maxproc != 1)
7298 Warning("Proxy '%s': in multi-process mode, stats will be"
7299 " limited to process assigned to the current request.\n",
7300 curproxy->id);
7301
Willy Tarreau102df612014-05-07 23:56:38 +02007302 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7303 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7304 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007305 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007306 }
Willy Tarreau102df612014-05-07 23:56:38 +02007307 if (curproxy->appsession_name) {
7308 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7309 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007310 }
Willy Tarreau102df612014-05-07 23:56:38 +02007311 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7312 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7313 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007314 }
7315 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007316
7317 /* create the task associated with the proxy */
7318 curproxy->task = task_new();
7319 if (curproxy->task) {
7320 curproxy->task->context = curproxy;
7321 curproxy->task->process = manage_proxy;
7322 /* no need to queue, it will be done automatically if some
7323 * listener gets limited.
7324 */
7325 curproxy->task->expire = TICK_ETERNITY;
7326 } else {
7327 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7328 curproxy->id);
7329 cfgerr++;
7330 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007331 }
7332
Willy Tarreaufbb78422011-06-05 15:38:35 +02007333 /* automatically compute fullconn if not set. We must not do it in the
7334 * loop above because cross-references are not yet fully resolved.
7335 */
7336 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7337 /* If <fullconn> is not set, let's set it to 10% of the sum of
7338 * the possible incoming frontend's maxconns.
7339 */
7340 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7341 struct proxy *fe;
7342 int total = 0;
7343
7344 /* sum up the number of maxconns of frontends which
7345 * reference this backend at least once or which are
7346 * the same one ('listen').
7347 */
7348 for (fe = proxy; fe; fe = fe->next) {
7349 struct switching_rule *rule;
7350 struct hdr_exp *exp;
7351 int found = 0;
7352
7353 if (!(fe->cap & PR_CAP_FE))
7354 continue;
7355
7356 if (fe == curproxy) /* we're on a "listen" instance */
7357 found = 1;
7358
7359 if (fe->defbe.be == curproxy) /* "default_backend" */
7360 found = 1;
7361
7362 /* check if a "use_backend" rule matches */
7363 if (!found) {
7364 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007365 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007366 found = 1;
7367 break;
7368 }
7369 }
7370 }
7371
7372 /* check if a "reqsetbe" rule matches */
7373 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7374 if (exp->action == ACT_SETBE &&
7375 (struct proxy *)exp->replace == curproxy) {
7376 found = 1;
7377 break;
7378 }
7379 }
7380
7381 /* now we've checked all possible ways to reference a backend
7382 * from a frontend.
7383 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007384 if (!found)
7385 continue;
7386 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007387 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007388 /* we have the sum of the maxconns in <total>. We only
7389 * keep 10% of that sum to set the default fullconn, with
7390 * a hard minimum of 1 (to avoid a divide by zero).
7391 */
7392 curproxy->fullconn = (total + 9) / 10;
7393 if (!curproxy->fullconn)
7394 curproxy->fullconn = 1;
7395 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007396 }
7397
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007398 /*
7399 * Recount currently required checks.
7400 */
7401
7402 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7403 int optnum;
7404
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007405 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7406 if (curproxy->options & cfg_opts[optnum].val)
7407 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007408
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007409 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7410 if (curproxy->options2 & cfg_opts2[optnum].val)
7411 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007412 }
7413
Willy Tarreaucdb5e922015-05-01 19:12:05 +02007414 /* compute the required process bindings for the peers */
7415 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7416 if (curproxy->table.peers.p)
7417 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7418
Willy Tarreau122541c2011-09-07 21:24:49 +02007419 if (peers) {
7420 struct peers *curpeers = peers, **last;
7421 struct peer *p, *pb;
7422
Willy Tarreauab0419d2015-05-01 19:15:17 +02007423 /* Remove all peers sections which don't have a valid listener,
7424 * which are not used by any table, or which are bound to more
7425 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02007426 */
7427 last = &peers;
7428 while (*last) {
7429 curpeers = *last;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007430
7431 if (curpeers->state == PR_STSTOPPED) {
7432 /* the "disabled" keyword was present */
7433 if (curpeers->peers_fe)
7434 stop_proxy(curpeers->peers_fe);
7435 curpeers->peers_fe = NULL;
7436 }
7437 else if (!curpeers->peers_fe) {
7438 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7439 curpeers->id, localpeer);
7440 }
David Carlier6de4c2f2015-07-02 07:00:17 +00007441 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreauab0419d2015-05-01 19:15:17 +02007442 /* either it's totally stopped or too much used */
7443 if (curpeers->peers_fe->bind_proc) {
7444 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreaua5d7d072015-05-04 21:48:51 +02007445 "running in different processes (%d different ones). "
7446 "Check global.nbproc and all tables' bind-process "
David Carlier6de4c2f2015-07-02 07:00:17 +00007447 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreauab0419d2015-05-01 19:15:17 +02007448 cfgerr++;
7449 }
7450 stop_proxy(curpeers->peers_fe);
7451 curpeers->peers_fe = NULL;
7452 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02007453 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007454 last = &curpeers->next;
7455 continue;
7456 }
7457
Willy Tarreau34d05b02015-05-01 20:02:17 +02007458 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007459 p = curpeers->remote;
7460 while (p) {
7461 pb = p->next;
7462 free(p->id);
7463 free(p);
7464 p = pb;
7465 }
7466
7467 /* Destroy and unlink this curpeers section.
7468 * Note: curpeers is backed up into *last.
7469 */
7470 free(curpeers->id);
7471 curpeers = curpeers->next;
7472 free(*last);
7473 *last = curpeers;
7474 }
7475 }
7476
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007477 /* initialize stick-tables on backend capable proxies. This must not
7478 * be done earlier because the data size may be discovered while parsing
7479 * other proxies.
7480 */
7481 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7482 if (curproxy->state == PR_STSTOPPED)
7483 continue;
7484
7485 if (!stktable_init(&curproxy->table)) {
7486 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7487 cfgerr++;
7488 }
7489 }
7490
Willy Tarreau34eb6712011-10-24 18:15:04 +02007491 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007492 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007493 MEM_F_SHARED);
7494
Willy Tarreaubb925012009-07-23 13:36:36 +02007495 if (cfgerr > 0)
7496 err_code |= ERR_ALERT | ERR_FATAL;
7497 out:
7498 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007499}
7500
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007501/*
7502 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7503 * parsing sessions.
7504 */
7505void cfg_register_keywords(struct cfg_kw_list *kwl)
7506{
7507 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7508}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007509
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007510/*
7511 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7512 */
7513void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7514{
7515 LIST_DEL(&kwl->list);
7516 LIST_INIT(&kwl->list);
7517}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007518
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007519/* this function register new section in the haproxy configuration file.
7520 * <section_name> is the name of this new section and <section_parser>
7521 * is the called parser. If two section declaration have the same name,
7522 * only the first declared is used.
7523 */
7524int cfg_register_section(char *section_name,
7525 int (*section_parser)(const char *, int, char **, int))
7526{
7527 struct cfg_section *cs;
7528
7529 cs = calloc(1, sizeof(*cs));
7530 if (!cs) {
7531 Alert("register section '%s': out of memory.\n", section_name);
7532 return 0;
7533 }
7534
7535 cs->section_name = section_name;
7536 cs->section_parser = section_parser;
7537
7538 LIST_ADDQ(&sections, &cs->list);
7539
7540 return 1;
7541}
7542
Willy Tarreaubaaee002006-06-26 02:48:02 +02007543/*
7544 * Local variables:
7545 * c-indent-level: 8
7546 * c-basic-offset: 8
7547 * End:
7548 */