blob: 260804ce0cfa6eb307fbfc9c7a01f41f9abad28f [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{
natalie.chen2d0e45b2015-04-22 14:10:12 +0800542 int i = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200544 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545
546 if (!strcmp(args[0], "global")) { /* new section */
547 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200550 else if (!strcmp(args[0], "ca-base")) {
551#ifdef USE_OPENSSL
552 if (global.ca_base != NULL) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.ca_base = strdup(args[1]);
563#else
564 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567#endif
568 }
569 else if (!strcmp(args[0], "crt-base")) {
570#ifdef USE_OPENSSL
571 if (global.crt_base != NULL) {
572 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT;
574 goto out;
575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.crt_base = strdup(args[1]);
582#else
583 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586#endif
587 }
natalie.chen7c92a9b2015-04-07 11:27:02 +0800588 else if (!strcmp(args[0], "email_alert")) {
589 global.email_alert = 1;
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : email_alert Expects email address as argument.\n", file, linenum);
592 global.email_alert = 0;
593 err_code |= ERR_ALERT;
594 goto out;
595 }
natalie.chen2d0e45b2015-04-22 14:10:12 +0800596 strncpy(global.email_from,args[1],50);
597 for (i=0; i<3; i++) {
598 if (*(args[i+2]) != 0)
599 strncpy(global.email_to[i],args[i+2],50);
natalie.chen7c92a9b2015-04-07 11:27:02 +0800600 }
natalie.chen2d0e45b2015-04-22 14:10:12 +0800601
natalie.chen7c92a9b2015-04-07 11:27:02 +0800602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 else if (!strcmp(args[0], "daemon")) {
604 global.mode |= MODE_DAEMON;
605 }
606 else if (!strcmp(args[0], "debug")) {
607 global.mode |= MODE_DEBUG;
608 }
609 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100610 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200612 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100613 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100616 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100618 else if (!strcmp(args[0], "nosplice")) {
619 global.tune.options &= ~GTUNE_USE_SPLICE;
620 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200621 else if (!strcmp(args[0], "nogetaddrinfo")) {
622 global.tune.options &= ~GTUNE_USE_GAI;
623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624 else if (!strcmp(args[0], "quiet")) {
625 global.mode |= MODE_QUIET;
626 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200627 else if (!strcmp(args[0], "tune.maxpollevents")) {
628 if (global.tune.maxpollevents != 0) {
629 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT;
631 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200632 }
633 if (*(args[1]) == 0) {
634 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200637 }
638 global.tune.maxpollevents = atol(args[1]);
639 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100640 else if (!strcmp(args[0], "tune.maxaccept")) {
641 if (global.tune.maxaccept != 0) {
642 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200643 err_code |= ERR_ALERT;
644 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100645 }
646 if (*(args[1]) == 0) {
647 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
649 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100650 }
651 global.tune.maxaccept = atol(args[1]);
652 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200653 else if (!strcmp(args[0], "tune.chksize")) {
654 if (*(args[1]) == 0) {
655 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
656 err_code |= ERR_ALERT | ERR_FATAL;
657 goto out;
658 }
659 global.tune.chksize = atol(args[1]);
660 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200661#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200662 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
663 global.tune.sslprivatecache = 1;
664 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100665 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
670 }
671 global.tune.sslcachesize = atol(args[1]);
672 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100673 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
674 unsigned int ssllifetime;
675 const char *res;
676
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682
683 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
684 if (res) {
685 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
686 file, linenum, *res, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690
691 global.tune.ssllifetime = ssllifetime;
692 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100693 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
698 }
699 global.tune.ssl_max_record = atol(args[1]);
700 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200701 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
702 if (*(args[1]) == 0) {
703 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 global.tune.ssl_default_dh_param = atol(args[1]);
708 if (global.tune.ssl_default_dh_param < 1024) {
709 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200714#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200715 else if (!strcmp(args[0], "tune.bufsize")) {
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.tune.bufsize = atol(args[1]);
722 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
723 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100724 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100725 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200726 }
727 else if (!strcmp(args[0], "tune.maxrewrite")) {
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 global.tune.maxrewrite = atol(args[1]);
734 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
735 global.tune.maxrewrite = global.tune.bufsize / 2;
736 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100737 else if (!strcmp(args[0], "tune.idletimer")) {
738 unsigned int idle;
739 const char *res;
740
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746
747 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
748 if (res) {
749 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
750 file, linenum, *res, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754
755 if (idle > 65535) {
756 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760 global.tune.idle_timer = idle;
761 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100762 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
763 if (global.tune.client_rcvbuf != 0) {
764 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
765 err_code |= ERR_ALERT;
766 goto out;
767 }
768 if (*(args[1]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 global.tune.client_rcvbuf = atol(args[1]);
774 }
775 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
776 if (global.tune.server_rcvbuf != 0) {
777 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT;
779 goto out;
780 }
781 if (*(args[1]) == 0) {
782 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786 global.tune.server_rcvbuf = atol(args[1]);
787 }
788 else if (!strcmp(args[0], "tune.sndbuf.client")) {
789 if (global.tune.client_sndbuf != 0) {
790 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT;
792 goto out;
793 }
794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.client_sndbuf = atol(args[1]);
800 }
801 else if (!strcmp(args[0], "tune.sndbuf.server")) {
802 if (global.tune.server_sndbuf != 0) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
804 err_code |= ERR_ALERT;
805 goto out;
806 }
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.server_sndbuf = atol(args[1]);
813 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200814 else if (!strcmp(args[0], "tune.pipesize")) {
815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.tune.pipesize = atol(args[1]);
821 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100822 else if (!strcmp(args[0], "tune.http.cookielen")) {
823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.tune.cookie_len = atol(args[1]) + 1;
829 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200830 else if (!strcmp(args[0], "tune.http.maxhdr")) {
831 if (*(args[1]) == 0) {
832 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836 global.tune.max_http_hdr = atol(args[1]);
837 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100838 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
839#ifdef USE_ZLIB
840 if (*args[1]) {
841 global.tune.zlibmemlevel = atoi(args[1]);
842 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
843 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
844 file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
848 } else {
849 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
850 file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854#else
855 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858#endif
859 }
860 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
861#ifdef USE_ZLIB
862 if (*args[1]) {
863 global.tune.zlibwindowsize = atoi(args[1]);
864 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
865 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
866 file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
870 } else {
871 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
872 file, linenum, args[0]);
873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
875 }
876#else
877 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880#endif
881 }
William Lallemandf3747832012-11-09 12:33:10 +0100882 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
883 if (*args[1]) {
884 global.tune.comp_maxlevel = atoi(args[1]);
885 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
886 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
887 file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 } else {
892 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
893 file, linenum, args[0]);
894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
896 }
897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 else if (!strcmp(args[0], "uid")) {
899 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200900 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200901 err_code |= ERR_ALERT;
902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903 }
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 global.uid = atol(args[1]);
910 }
911 else if (!strcmp(args[0], "gid")) {
912 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200913 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200914 err_code |= ERR_ALERT;
915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 }
917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 }
922 global.gid = atol(args[1]);
923 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200924 /* user/group name handling */
925 else if (!strcmp(args[0], "user")) {
926 struct passwd *ha_user;
927 if (global.uid != 0) {
928 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT;
930 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200931 }
932 errno = 0;
933 ha_user = getpwnam(args[1]);
934 if (ha_user != NULL) {
935 global.uid = (int)ha_user->pw_uid;
936 }
937 else {
938 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 +0200939 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200940 }
941 }
942 else if (!strcmp(args[0], "group")) {
943 struct group *ha_group;
944 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200945 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT;
947 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200948 }
949 errno = 0;
950 ha_group = getgrnam(args[1]);
951 if (ha_group != NULL) {
952 global.gid = (int)ha_group->gr_gid;
953 }
954 else {
955 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 +0200956 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200957 }
958 }
959 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 if (*(args[1]) == 0) {
962 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 }
966 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100967 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
968 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
969 file, linenum, args[0], LONGBITS, global.nbproc);
970 err_code |= ERR_ALERT | ERR_FATAL;
971 goto out;
972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 else if (!strcmp(args[0], "maxconn")) {
975 if (global.maxconn != 0) {
976 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT;
978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200979 }
980 if (*(args[1]) == 0) {
981 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 }
985 global.maxconn = atol(args[1]);
986#ifdef SYSTEM_MAXCONN
987 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
988 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);
989 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200990 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 }
992#endif /* SYSTEM_MAXCONN */
993 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200994 else if (!strcmp(args[0], "maxsslconn")) {
995#ifdef USE_OPENSSL
996 if (*(args[1]) == 0) {
997 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 global.maxsslconn = atol(args[1]);
1002#else
Emeric Brun0914df82012-10-02 18:45:42 +02001003 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001006#endif
1007 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001008 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1009#ifdef USE_OPENSSL
1010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
1014 }
1015 free(global.listen_default_ciphers);
1016 global.listen_default_ciphers = strdup(args[1]);
1017#else
1018 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
1021#endif
1022 }
1023 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1024#ifdef USE_OPENSSL
1025 if (*(args[1]) == 0) {
1026 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 free(global.connect_default_ciphers);
1031 global.connect_default_ciphers = strdup(args[1]);
1032#else
1033 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036#endif
1037 }
Emeric Brun850efd52014-01-29 12:24:34 +01001038 else if (!strcmp(args[0], "ssl-server-verify")) {
1039 if (*(args[1]) == 0) {
1040 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044 if (strcmp(args[1],"none") == 0)
1045 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1046 else if (strcmp(args[1],"required") == 0)
1047 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1048 else {
1049 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
1052 }
1053 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001054 else if (!strcmp(args[0], "maxconnrate")) {
1055 if (global.cps_lim != 0) {
1056 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1057 err_code |= ERR_ALERT;
1058 goto out;
1059 }
1060 if (*(args[1]) == 0) {
1061 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 global.cps_lim = atol(args[1]);
1066 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001067 else if (!strcmp(args[0], "maxsessrate")) {
1068 if (global.sps_lim != 0) {
1069 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT;
1071 goto out;
1072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
1077 }
1078 global.sps_lim = atol(args[1]);
1079 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001080 else if (!strcmp(args[0], "maxsslrate")) {
1081 if (global.ssl_lim != 0) {
1082 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1083 err_code |= ERR_ALERT;
1084 goto out;
1085 }
1086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 global.ssl_lim = atol(args[1]);
1092 }
William Lallemandd85f9172012-11-09 17:05:39 +01001093 else if (!strcmp(args[0], "maxcomprate")) {
1094 if (*(args[1]) == 0) {
1095 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
1098 }
1099 global.comp_rate_lim = atoi(args[1]) * 1024;
1100 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001101 else if (!strcmp(args[0], "maxpipes")) {
1102 if (global.maxpipes != 0) {
1103 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001104 err_code |= ERR_ALERT;
1105 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001106 }
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001111 }
1112 global.maxpipes = atol(args[1]);
1113 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001114 else if (!strcmp(args[0], "maxzlibmem")) {
1115 if (*(args[1]) == 0) {
1116 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto out;
1119 }
William Lallemande3a7d992012-11-20 11:25:20 +01001120 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001121 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001122 else if (!strcmp(args[0], "maxcompcpuusage")) {
1123 if (*(args[1]) == 0) {
1124 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001129 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001130 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
1133 }
1134}
1135
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 else if (!strcmp(args[0], "ulimit-n")) {
1137 if (global.rlimit_nofile != 0) {
1138 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001139 err_code |= ERR_ALERT;
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 }
1142 if (*(args[1]) == 0) {
1143 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001144 err_code |= ERR_ALERT | ERR_FATAL;
1145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146 }
1147 global.rlimit_nofile = atol(args[1]);
1148 }
1149 else if (!strcmp(args[0], "chroot")) {
1150 if (global.chroot != NULL) {
1151 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT;
1153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
1155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 }
1160 global.chroot = strdup(args[1]);
1161 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001162 else if (!strcmp(args[0], "description")) {
1163 int i, len=0;
1164 char *d;
1165
1166 if (!*args[1]) {
1167 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1168 file, linenum, args[0]);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto out;
1171 }
1172
Willy Tarreau348acfe2014-04-14 15:00:39 +02001173 for (i = 1; *args[i]; i++)
1174 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001175
1176 if (global.desc)
1177 free(global.desc);
1178
1179 global.desc = d = (char *)calloc(1, len);
1180
Willy Tarreau348acfe2014-04-14 15:00:39 +02001181 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1182 for (i = 2; *args[i]; i++)
1183 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001184 }
1185 else if (!strcmp(args[0], "node")) {
1186 int i;
1187 char c;
1188
1189 for (i=0; args[1][i]; i++) {
1190 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001191 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1192 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001193 break;
1194 }
1195
1196 if (!i || args[1][i]) {
1197 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1198 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1199 file, linenum, args[0]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203
1204 if (global.node)
1205 free(global.node);
1206
1207 global.node = strdup(args[1]);
1208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 else if (!strcmp(args[0], "pidfile")) {
1210 if (global.pidfile != NULL) {
1211 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001212 err_code |= ERR_ALERT;
1213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
1215 if (*(args[1]) == 0) {
1216 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 global.pidfile = strdup(args[1]);
1221 }
Emeric Bruned760922010-10-22 17:59:25 +02001222 else if (!strcmp(args[0], "unix-bind")) {
1223 int cur_arg = 1;
1224 while (*(args[cur_arg])) {
1225 if (!strcmp(args[cur_arg], "prefix")) {
1226 if (global.unix_bind.prefix != NULL) {
1227 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1228 err_code |= ERR_ALERT;
1229 cur_arg += 2;
1230 continue;
1231 }
1232
1233 if (*(args[cur_arg+1]) == 0) {
1234 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1239 cur_arg += 2;
1240 continue;
1241 }
1242
1243 if (!strcmp(args[cur_arg], "mode")) {
1244
1245 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1246 cur_arg += 2;
1247 continue;
1248 }
1249
1250 if (!strcmp(args[cur_arg], "uid")) {
1251
1252 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1253 cur_arg += 2;
1254 continue;
1255 }
1256
1257 if (!strcmp(args[cur_arg], "gid")) {
1258
1259 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (!strcmp(args[cur_arg], "user")) {
1265 struct passwd *user;
1266
1267 user = getpwnam(args[cur_arg + 1]);
1268 if (!user) {
1269 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1270 file, linenum, args[0], args[cur_arg + 1 ]);
1271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
1273 }
1274
1275 global.unix_bind.ux.uid = user->pw_uid;
1276 cur_arg += 2;
1277 continue;
1278 }
1279
1280 if (!strcmp(args[cur_arg], "group")) {
1281 struct group *group;
1282
1283 group = getgrnam(args[cur_arg + 1]);
1284 if (!group) {
1285 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1286 file, linenum, args[0], args[cur_arg + 1 ]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290
1291 global.unix_bind.ux.gid = group->gr_gid;
1292 cur_arg += 2;
1293 continue;
1294 }
1295
Willy Tarreaub48f9582011-09-05 01:17:06 +02001296 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001297 file, linenum, args[0]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301 }
William Lallemand0f99e342011-10-12 17:50:54 +02001302 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1303 /* delete previous herited or defined syslog servers */
1304 struct logsrv *back;
1305 struct logsrv *tmp;
1306
1307 if (*(args[1]) != 0) {
1308 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
1311 }
1312
1313 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1314 LIST_DEL(&tmp->list);
1315 free(tmp);
1316 }
1317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001319 struct sockaddr_storage *sk;
1320 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001321 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001322 int arg = 0;
1323 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001324
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 if (*(args[1]) == 0 || *(args[2]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329 }
William Lallemand0f99e342011-10-12 17:50:54 +02001330
1331 logsrv = calloc(1, sizeof(struct logsrv));
1332
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001333 /* just after the address, a length may be specified */
1334 if (strcmp(args[arg+2], "len") == 0) {
1335 len = atoi(args[arg+3]);
1336 if (len < 80 || len > 65535) {
1337 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1338 file, linenum, args[arg+3]);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342 logsrv->maxlen = len;
1343
1344 /* skip these two args */
1345 arg += 2;
1346 }
1347 else
1348 logsrv->maxlen = MAX_SYSLOG_LEN;
1349
1350 if (logsrv->maxlen > global.max_syslog_len) {
1351 global.max_syslog_len = logsrv->maxlen;
1352 logline = realloc(logline, global.max_syslog_len + 1);
1353 }
1354
1355 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001356 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001357 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001358 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001359 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 }
1361
William Lallemand0f99e342011-10-12 17:50:54 +02001362 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001363 if (*(args[arg+3])) {
1364 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001365 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001366 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001367 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001368 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 }
1370 }
1371
William Lallemand0f99e342011-10-12 17:50:54 +02001372 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001373 if (*(args[arg+4])) {
1374 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001375 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001376 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001377 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001378 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001379 }
1380 }
1381
Willy Tarreau902636f2013-03-10 19:44:48 +01001382 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001383 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001384 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001385 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001386 free(logsrv);
1387 goto out;
1388 }
1389 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001390
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001391 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001392 if (port1 != port2) {
1393 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1394 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001395 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001396 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001397 goto out;
1398 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001399
William Lallemand0f99e342011-10-12 17:50:54 +02001400 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001401 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001402 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404
William Lallemand0f99e342011-10-12 17:50:54 +02001405 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001406 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001407 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1408 char *name;
1409 int len;
1410
1411 if (global.log_send_hostname != NULL) {
1412 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1413 err_code |= ERR_ALERT;
1414 goto out;
1415 }
1416
1417 if (*(args[1]))
1418 name = args[1];
1419 else
1420 name = hostname;
1421
1422 len = strlen(name);
1423
1424 /* We'll add a space after the name to respect the log format */
1425 free(global.log_send_hostname);
1426 global.log_send_hostname = malloc(len + 2);
1427 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1428 }
Kevinm48936af2010-12-22 16:08:21 +00001429 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1430 if (*(args[1]) == 0) {
1431 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1432 err_code |= ERR_ALERT | ERR_FATAL;
1433 goto out;
1434 }
1435 free(global.log_tag);
1436 global.log_tag = strdup(args[1]);
1437 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001438 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1439 if (global.spread_checks != 0) {
1440 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001441 err_code |= ERR_ALERT;
1442 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001443 }
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001448 }
1449 global.spread_checks = atol(args[1]);
1450 if (global.spread_checks < 0 || global.spread_checks > 50) {
1451 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001452 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001455 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1456 const char *err;
1457 unsigned int val;
1458
1459
1460 if (*(args[1]) == 0) {
1461 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1462 err_code |= ERR_ALERT | ERR_FATAL;
1463 goto out;
1464 }
1465
1466 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1467 if (err) {
1468 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1469 err_code |= ERR_ALERT | ERR_FATAL;
1470 }
1471 global.max_spread_checks = val;
1472 if (global.max_spread_checks < 0) {
1473 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1474 err_code |= ERR_ALERT | ERR_FATAL;
1475 }
1476 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001477 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1478#ifdef USE_CPU_AFFINITY
1479 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001480 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001481 unsigned long cpus = 0;
1482
1483 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001484 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001485 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001486 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001487 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001488 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001489 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001490 proc = atol(args[1]);
1491 if (proc >= 1 && proc <= LONGBITS)
1492 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001493 }
1494
1495 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001496 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",
1497 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 cur_arg = 2;
1503 while (*args[cur_arg]) {
1504 unsigned int low, high;
1505
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001506 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001507 char *dash = strchr(args[cur_arg], '-');
1508
1509 low = high = str2uic(args[cur_arg]);
1510 if (dash)
1511 high = str2uic(dash + 1);
1512
1513 if (high < low) {
1514 unsigned int swap = low;
1515 low = high;
1516 high = swap;
1517 }
1518
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001519 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001520 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001521 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
1524 }
1525
1526 while (low <= high)
1527 cpus |= 1UL << low++;
1528 }
1529 else {
1530 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1531 file, linenum, args[0], args[cur_arg]);
1532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
1534 }
1535 cur_arg++;
1536 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001537 for (i = 0; i < LONGBITS; i++)
1538 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001539 global.cpu_map[i] = cpus;
1540#else
1541 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1542 err_code |= ERR_ALERT | ERR_FATAL;
1543 goto out;
1544#endif
1545 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001546 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001547 struct cfg_kw_list *kwl;
1548 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001549 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001550
1551 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1552 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1553 if (kwl->kw[index].section != CFG_GLOBAL)
1554 continue;
1555 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001556 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001557 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001558 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001560 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001561 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001562 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001563 err_code |= ERR_WARN;
1564 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001565 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001566 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001567 }
1568 }
1569 }
1570
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001572 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001574
Willy Tarreau058e9072009-07-20 09:30:05 +02001575 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001576 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001577 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578}
1579
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001580void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001582 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 defproxy.mode = PR_MODE_TCP;
1584 defproxy.state = PR_STNEW;
1585 defproxy.maxconn = cfg_maxpconn;
1586 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001587
Simon Horman66183002013-02-23 10:16:43 +09001588 defproxy.defsrv.check.inter = DEF_CHKINTR;
1589 defproxy.defsrv.check.fastinter = 0;
1590 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001591 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1592 defproxy.defsrv.agent.fastinter = 0;
1593 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001594 defproxy.defsrv.check.rise = DEF_RISETIME;
1595 defproxy.defsrv.check.fall = DEF_FALLTIME;
1596 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1597 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001598 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001599 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001600 defproxy.defsrv.maxqueue = 0;
1601 defproxy.defsrv.minconn = 0;
1602 defproxy.defsrv.maxconn = 0;
1603 defproxy.defsrv.slowstart = 0;
1604 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1605 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1606 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607}
1608
Willy Tarreauade5ec42010-01-28 19:33:49 +01001609
Willy Tarreau63af98d2014-05-18 08:11:41 +02001610/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1611 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1612 * ERR_FATAL in case of error.
1613 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614static int create_cond_regex_rule(const char *file, int line,
1615 struct proxy *px, int dir, int action, int flags,
1616 const char *cmd, const char *reg, const char *repl,
1617 const char **cond_start)
1618{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001619 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001620 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001621 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001622 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001623 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001624 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001625 int cs;
1626 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001627
1628 if (px == &defproxy) {
1629 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001630 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001631 goto err;
1632 }
1633
1634 if (*reg == 0) {
1635 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001636 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001637 goto err;
1638 }
1639
1640 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001641 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001642
Willy Tarreau5321c422010-01-28 20:35:13 +01001643 if (cond_start &&
1644 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001645 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1646 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1647 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001648 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001649 goto err;
1650 }
1651 }
1652 else if (cond_start && **cond_start) {
1653 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1654 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001655 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001656 goto err;
1657 }
1658
Willy Tarreau63af98d2014-05-18 08:11:41 +02001659 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001660 (dir == SMP_OPT_DIR_REQ) ?
1661 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1662 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1663 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001664
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001665 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 if (!preg) {
1667 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001668 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001669 goto err;
1670 }
1671
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001672 cs = !(flags & REG_ICASE);
1673 cap = !(flags & REG_NOSUB);
1674 error = NULL;
1675 if (!regex_comp(reg, preg, cs, cap, &error)) {
1676 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1677 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001678 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001679 goto err;
1680 }
1681
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001682 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001683 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001684 if (repl && err) {
1685 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1686 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001687 ret_code |= ERR_ALERT | ERR_FATAL;
1688 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001689 }
1690
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001691 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001692 ret_code |= ERR_WARN;
1693
1694 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001695
Willy Tarreau63af98d2014-05-18 08:11:41 +02001696 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001697 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001698 err:
1699 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001700 free(errmsg);
1701 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001702}
1703
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001705 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001706 * Returns the error code, 0 if OK, or any combination of :
1707 * - ERR_ABORT: must abort ASAP
1708 * - ERR_FATAL: we can continue parsing but not start the service
1709 * - ERR_WARN: a warning has been emitted
1710 * - ERR_ALERT: an alert has been emitted
1711 * Only the two first ones can stop processing, the two others are just
1712 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001714int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1715{
1716 static struct peers *curpeers = NULL;
1717 struct peer *newpeer = NULL;
1718 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 struct bind_conf *bind_conf;
1720 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001722 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001723
1724 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001725 if (!*args[1]) {
1726 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001727 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001728 goto out;
1729 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001730
1731 err = invalid_char(args[1]);
1732 if (err) {
1733 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1734 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001735 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001736 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001737 }
1738
1739 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1740 /*
1741 * If there are two proxies with the same name only following
1742 * combinations are allowed:
1743 */
1744 if (strcmp(curpeers->id, args[1]) == 0) {
1745 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1746 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1747 err_code |= ERR_WARN;
1748 }
1749 }
1750
1751 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1752 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1753 err_code |= ERR_ALERT | ERR_ABORT;
1754 goto out;
1755 }
1756
1757 curpeers->next = peers;
1758 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001759 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001760 curpeers->conf.line = linenum;
1761 curpeers->last_change = now.tv_sec;
1762 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001763 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001764 }
1765 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001766 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001767 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001768 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001769
1770 if (!*args[2]) {
1771 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1772 file, linenum, args[0]);
1773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
1775 }
1776
1777 err = invalid_char(args[1]);
1778 if (err) {
1779 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1780 file, linenum, *err, args[1]);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1786 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1787 err_code |= ERR_ALERT | ERR_ABORT;
1788 goto out;
1789 }
1790
1791 /* the peers are linked backwards first */
1792 curpeers->count++;
1793 newpeer->next = curpeers->remote;
1794 curpeers->remote = newpeer;
1795 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001796 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001797 newpeer->conf.line = linenum;
1798
1799 newpeer->last_change = now.tv_sec;
1800 newpeer->id = strdup(args[1]);
1801
Willy Tarreau902636f2013-03-10 19:44:48 +01001802 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001803 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001804 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001807 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001808
1809 proto = protocol_by_family(sk->ss_family);
1810 if (!proto || !proto->connect) {
1811 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1812 file, linenum, args[0], args[1]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001816
1817 if (port1 != port2) {
1818 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1819 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
1822 }
1823
Willy Tarreau2aa38802013-02-20 19:20:59 +01001824 if (!port1) {
1825 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1826 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001827 err_code |= ERR_ALERT | ERR_FATAL;
1828 goto out;
1829 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001830
Emeric Brun32da3c42010-09-23 18:39:19 +02001831 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001832 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001833 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001834 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001835
Emeric Brun32da3c42010-09-23 18:39:19 +02001836 if (strcmp(newpeer->id, localpeer) == 0) {
1837 /* Current is local peer, it define a frontend */
1838 newpeer->local = 1;
1839
1840 if (!curpeers->peers_fe) {
1841 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1842 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1843 err_code |= ERR_ALERT | ERR_ABORT;
1844 goto out;
1845 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001846
Willy Tarreau237250c2011-07-29 01:49:03 +02001847 init_new_proxy(curpeers->peers_fe);
1848 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001849
1850 curpeers->peers_fe->last_change = now.tv_sec;
1851 curpeers->peers_fe->id = strdup(args[1]);
1852 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001853 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001854 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001855 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001856 curpeers->peers_fe->accept = peer_accept;
1857 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001858 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1859 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreaucdb5e922015-05-01 19:12:05 +02001860 curpeers->peers_fe->bind_proc = 0; /* will be filled by users */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001861
1862 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1863
Willy Tarreau902636f2013-03-10 19:44:48 +01001864 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1865 if (errmsg && *errmsg) {
1866 indent_msg(&errmsg, 2);
1867 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001868 }
1869 else
1870 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1871 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001872 err_code |= ERR_FATAL;
1873 goto out;
1874 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001875
1876 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001877 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001878 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1879 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1880 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1881 l->accept = session_accept;
1882 l->handler = process_session;
1883 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1884 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1885 global.maxsock += l->maxconn;
1886 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001887 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001888 else {
1889 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1890 file, linenum, args[0], args[1],
1891 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1892 err_code |= ERR_FATAL;
1893 goto out;
1894 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001895 }
1896 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001897 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1898 curpeers->state = PR_STSTOPPED;
1899 }
1900 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1901 curpeers->state = PR_STNEW;
1902 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001903 else if (*args[0] != 0) {
1904 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
1907 }
1908
1909out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001910 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 return err_code;
1912}
1913
Willy Tarreau3842f002009-06-14 11:39:52 +02001914int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915{
1916 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001917 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001918 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001919 int rc;
1920 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001921 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001922 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001923 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001924 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001925 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926
Willy Tarreau977b8e42006-12-29 14:19:17 +01001927 if (!strcmp(args[0], "listen"))
1928 rc = PR_CAP_LISTEN;
1929 else if (!strcmp(args[0], "frontend"))
1930 rc = PR_CAP_FE | PR_CAP_RS;
1931 else if (!strcmp(args[0], "backend"))
1932 rc = PR_CAP_BE | PR_CAP_RS;
1933 else if (!strcmp(args[0], "ruleset"))
1934 rc = PR_CAP_RS;
1935 else
1936 rc = PR_CAP_NONE;
1937
1938 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001939 struct ebpt_node *node;
1940
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 if (!*args[1]) {
1942 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1943 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001945 err_code |= ERR_ALERT | ERR_ABORT;
1946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001948
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001949 err = invalid_char(args[1]);
1950 if (err) {
1951 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1952 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001954 }
1955
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001956 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1957 curproxy = container_of(node, struct proxy, conf.by_name);
1958
1959 if (strcmp(curproxy->id, args[1]) != 0)
1960 break;
1961
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001962 /*
1963 * If there are two proxies with the same name only following
1964 * combinations are allowed:
1965 *
1966 * listen backend frontend ruleset
1967 * listen - - - -
1968 * backend - - OK -
1969 * frontend - OK - -
1970 * ruleset - - - -
1971 */
1972
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001973 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1974 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001975 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1976 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1977 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001978 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001979 }
1980 }
1981
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1983 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001984 err_code |= ERR_ALERT | ERR_ABORT;
1985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001987
Willy Tarreau97cb7802010-01-03 20:23:58 +01001988 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 curproxy->next = proxy;
1990 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001991 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1992 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001993 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001995 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001996 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997
1998 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001999 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002000 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002001
Willy Tarreau4348fad2012-09-20 16:48:07 +02002002 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2003
Willy Tarreau902636f2013-03-10 19:44:48 +01002004 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2005 if (errmsg && *errmsg) {
2006 indent_msg(&errmsg, 2);
2007 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002008 }
2009 else
2010 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2011 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002012 err_code |= ERR_FATAL;
2013 goto out;
2014 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002015
Willy Tarreau4348fad2012-09-20 16:48:07 +02002016 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002017 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002019 }
2020
2021 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002022 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002023 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002024
Willy Tarreaubaaee002006-06-26 02:48:02 +02002025 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002027 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002028 curproxy->no_options = defproxy.no_options;
2029 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002030 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002031 curproxy->except_net = defproxy.except_net;
2032 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002033 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002034 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002036 if (defproxy.fwdfor_hdr_len) {
2037 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2038 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2039 }
2040
Willy Tarreaub86db342009-11-30 11:50:16 +01002041 if (defproxy.orgto_hdr_len) {
2042 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2043 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2044 }
2045
Mark Lamourinec2247f02012-01-04 13:02:01 -05002046 if (defproxy.server_id_hdr_len) {
2047 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2048 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2049 }
2050
Willy Tarreau977b8e42006-12-29 14:19:17 +01002051 if (curproxy->cap & PR_CAP_FE) {
2052 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002053 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002054 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002055
2056 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002057 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2058 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002059
2060 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002064 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002065 curproxy->fullconn = defproxy.fullconn;
2066 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002067 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002069 if (defproxy.check_req) {
2070 curproxy->check_req = calloc(1, defproxy.check_len);
2071 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2072 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002075 if (defproxy.expect_str) {
2076 curproxy->expect_str = strdup(defproxy.expect_str);
2077 if (defproxy.expect_regex) {
2078 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002079 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2080 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002081 }
2082 }
2083
Willy Tarreau67402132012-05-31 20:40:20 +02002084 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002085 if (defproxy.cookie_name)
2086 curproxy->cookie_name = strdup(defproxy.cookie_name);
2087 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002088 if (defproxy.cookie_domain)
2089 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002090
Willy Tarreau31936852010-10-06 16:59:56 +02002091 if (defproxy.cookie_maxidle)
2092 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2093
2094 if (defproxy.cookie_maxlife)
2095 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2096
Emeric Brun647caf12009-06-30 17:57:00 +02002097 if (defproxy.rdp_cookie_name)
2098 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2099 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2100
Willy Tarreau01732802007-11-01 22:48:15 +01002101 if (defproxy.url_param_name)
2102 curproxy->url_param_name = strdup(defproxy.url_param_name);
2103 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002104
Benoitaffb4812009-03-25 13:02:10 +01002105 if (defproxy.hh_name)
2106 curproxy->hh_name = strdup(defproxy.hh_name);
2107 curproxy->hh_len = defproxy.hh_len;
2108 curproxy->hh_match_domain = defproxy.hh_match_domain;
2109
Willy Tarreauef9a3602012-12-08 22:29:20 +01002110 if (defproxy.conn_src.iface_name)
2111 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2112 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002113 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002114#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002115 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002116#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002119 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002120 if (defproxy.capture_name)
2121 curproxy->capture_name = strdup(defproxy.capture_name);
2122 curproxy->capture_namelen = defproxy.capture_namelen;
2123 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125
Willy Tarreau977b8e42006-12-29 14:19:17 +01002126 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002127 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002128 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002129 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002130 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002131 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002132 curproxy->mon_net = defproxy.mon_net;
2133 curproxy->mon_mask = defproxy.mon_mask;
2134 if (defproxy.monitor_uri)
2135 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2136 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002137 if (defproxy.defbe.name)
2138 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002139
2140 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002141 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2142 if (curproxy->conf.logformat_string &&
2143 curproxy->conf.logformat_string != default_http_log_format &&
2144 curproxy->conf.logformat_string != default_tcp_log_format &&
2145 curproxy->conf.logformat_string != clf_http_log_format)
2146 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2147
2148 if (defproxy.conf.lfs_file) {
2149 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2150 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2151 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 }
2153
2154 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002155 curproxy->timeout.connect = defproxy.timeout.connect;
2156 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002157 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002158 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002159 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002160 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002161 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002162 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002163 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002164 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002165 }
2166
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002168 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002169
2170 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002171 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002172 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002173 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002174 LIST_INIT(&node->list);
2175 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2176 }
2177
Willy Tarreau62a61232013-04-12 18:13:46 +02002178 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2179 if (curproxy->conf.uniqueid_format_string)
2180 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2181
2182 if (defproxy.conf.uif_file) {
2183 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2184 curproxy->conf.uif_line = defproxy.conf.uif_line;
2185 }
William Lallemanda73203e2012-03-12 12:48:57 +01002186
2187 /* copy default header unique id */
2188 if (defproxy.header_unique_id)
2189 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2190
William Lallemand82fe75c2012-10-23 10:25:10 +02002191 /* default compression options */
2192 if (defproxy.comp != NULL) {
2193 curproxy->comp = calloc(1, sizeof(struct comp));
2194 curproxy->comp->algos = defproxy.comp->algos;
2195 curproxy->comp->types = defproxy.comp->types;
2196 }
2197
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002199 curproxy->conf.used_listener_id = EB_ROOT;
2200 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002201
Willy Tarreau93893792009-07-23 13:19:11 +02002202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
2204 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2205 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002206 /* FIXME-20070101: we should do this too at the end of the
2207 * config parsing to free all default values.
2208 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002209 free(defproxy.check_req);
2210 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002211 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002212 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002213 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002214 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002215 free(defproxy.capture_name);
2216 free(defproxy.monitor_uri);
2217 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002218 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002219 free(defproxy.fwdfor_hdr_name);
2220 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002221 free(defproxy.orgto_hdr_name);
2222 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002223 free(defproxy.server_id_hdr_name);
2224 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002225 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002226 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002227 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002228 free(defproxy.expect_regex);
2229 defproxy.expect_regex = NULL;
2230 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002231
Willy Tarreau62a61232013-04-12 18:13:46 +02002232 if (defproxy.conf.logformat_string != default_http_log_format &&
2233 defproxy.conf.logformat_string != default_tcp_log_format &&
2234 defproxy.conf.logformat_string != clf_http_log_format)
2235 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002236
Willy Tarreau62a61232013-04-12 18:13:46 +02002237 free(defproxy.conf.uniqueid_format_string);
2238 free(defproxy.conf.lfs_file);
2239 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002240
Willy Tarreaua534fea2008-08-03 12:19:50 +02002241 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002242 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002243
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 /* we cannot free uri_auth because it might already be used */
2245 init_default_instance();
2246 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002247 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2248 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002249 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
2252 else if (curproxy == NULL) {
2253 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002257
2258 /* update the current file and line being parsed */
2259 curproxy->conf.args.file = curproxy->conf.file;
2260 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002261
2262 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002263 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2264 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2265 if (err_code & ERR_FATAL)
2266 goto out;
2267 }
2268 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002269 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002270 int cur_arg;
2271
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 if (curproxy == &defproxy) {
2273 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279
Willy Tarreau24709282013-03-10 21:32:12 +01002280 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002281 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002286
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002287 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002288
2289 /* use default settings for unix sockets */
2290 bind_conf->ux.uid = global.unix_bind.ux.uid;
2291 bind_conf->ux.gid = global.unix_bind.ux.gid;
2292 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002293
2294 /* NOTE: the following line might create several listeners if there
2295 * are comma-separated IPs or port ranges. So all further processing
2296 * will have to be applied to all listeners created after last_listen.
2297 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002298 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2299 if (errmsg && *errmsg) {
2300 indent_msg(&errmsg, 2);
2301 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002302 }
2303 else
2304 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2305 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002309
Willy Tarreau4348fad2012-09-20 16:48:07 +02002310 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2311 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002312 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002313 }
2314
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002315 cur_arg = 2;
2316 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002317 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002318 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002319 char *err;
2320
Willy Tarreau26982662012-09-12 23:17:10 +02002321 kw = bind_find_kw(args[cur_arg]);
2322 if (kw) {
2323 char *err = NULL;
2324 int code;
2325
2326 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002327 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2328 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002329 cur_arg += 1 + kw->skip ;
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333
Willy Tarreau4348fad2012-09-20 16:48:07 +02002334 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002335 err_code |= code;
2336
2337 if (code) {
2338 if (err && *err) {
2339 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002340 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002341 }
2342 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002343 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2344 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002345 if (code & ERR_FATAL) {
2346 free(err);
2347 cur_arg += 1 + kw->skip;
2348 goto out;
2349 }
2350 }
2351 free(err);
2352 cur_arg += 1 + kw->skip;
2353 continue;
2354 }
2355
Willy Tarreau8638f482012-09-18 18:01:17 +02002356 err = NULL;
2357 if (!bind_dumped) {
2358 bind_dump_kws(&err);
2359 indent_msg(&err, 4);
2360 bind_dumped = 1;
2361 }
2362
2363 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2364 file, linenum, args[0], args[1], args[cur_arg],
2365 err ? " Registered keywords :" : "", err ? err : "");
2366 free(err);
2367
Willy Tarreau93893792009-07-23 13:19:11 +02002368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002370 }
Willy Tarreau93893792009-07-23 13:19:11 +02002371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002374 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2376 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002380 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002382
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 /* flush useless bits */
2384 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002387 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002388 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002389 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390
Willy Tarreau1c47f852006-07-09 08:22:27 +02002391 if (!*args[1]) {
2392 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2393 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002396 }
2397
Willy Tarreaua534fea2008-08-03 12:19:50 +02002398 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002399 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002400 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002401 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002402 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2403
Willy Tarreau93893792009-07-23 13:19:11 +02002404 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2407 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2408 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2409 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2410 else {
2411 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 }
2415 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002416 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002417 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002418
2419 if (curproxy == &defproxy) {
2420 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2421 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002424 }
2425
2426 if (!*args[1]) {
2427 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002431 }
2432
2433 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002434 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002435
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002436 if (curproxy->uuid <= 0) {
2437 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002438 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002441 }
2442
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002443 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2444 if (node) {
2445 struct proxy *target = container_of(node, struct proxy, conf.id);
2446 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2447 file, linenum, proxy_type_str(curproxy), curproxy->id,
2448 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002453 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002454 else if (!strcmp(args[0], "description")) {
2455 int i, len=0;
2456 char *d;
2457
Cyril Bonté99ed3272010-01-24 23:29:44 +01002458 if (curproxy == &defproxy) {
2459 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2460 file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002465 if (!*args[1]) {
2466 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2467 file, linenum, args[0]);
2468 return -1;
2469 }
2470
Willy Tarreau348acfe2014-04-14 15:00:39 +02002471 for (i = 1; *args[i]; i++)
2472 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002473
2474 d = (char *)calloc(1, len);
2475 curproxy->desc = d;
2476
Willy Tarreau348acfe2014-04-14 15:00:39 +02002477 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2478 for (i = 2; *args[i]; i++)
2479 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002480
2481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2483 curproxy->state = PR_STSTOPPED;
2484 }
2485 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2486 curproxy->state = PR_STNEW;
2487 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002488 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2489 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002490 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002491
2492 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002493 unsigned int low, high;
2494
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002495 if (strcmp(args[cur_arg], "all") == 0) {
2496 set = 0;
2497 break;
2498 }
2499 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002500 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002501 }
2502 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002503 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002504 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002505 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002506 char *dash = strchr(args[cur_arg], '-');
2507
2508 low = high = str2uic(args[cur_arg]);
2509 if (dash)
2510 high = str2uic(dash + 1);
2511
2512 if (high < low) {
2513 unsigned int swap = low;
2514 low = high;
2515 high = swap;
2516 }
2517
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002518 if (low < 1 || high > LONGBITS) {
2519 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2520 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002523 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002524 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002525 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002526 }
2527 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002528 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2529 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002532 }
2533 cur_arg++;
2534 }
2535 curproxy->bind_proc = set;
2536 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002537 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002542 }
2543
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002544 err = invalid_char(args[1]);
2545 if (err) {
2546 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2547 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002549 }
2550
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002551 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002552 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2553 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002556 }
2557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2559 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 if (*(args[1]) == 0) {
2565 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2566 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002570
Willy Tarreau67402132012-05-31 20:40:20 +02002571 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002572 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002573 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002574 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 curproxy->cookie_name = strdup(args[1]);
2576 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002577
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 cur_arg = 2;
2579 while (*(args[cur_arg])) {
2580 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002581 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
2583 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002584 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
2586 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002587 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
2589 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002590 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 }
2592 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002593 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002595 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002596 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002599 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002601 else if (!strcmp(args[cur_arg], "httponly")) {
2602 curproxy->ck_opts |= PR_CK_HTTPONLY;
2603 }
2604 else if (!strcmp(args[cur_arg], "secure")) {
2605 curproxy->ck_opts |= PR_CK_SECURE;
2606 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002607 else if (!strcmp(args[cur_arg], "domain")) {
2608 if (!*args[cur_arg + 1]) {
2609 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2610 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002613 }
2614
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002615 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002616 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002617 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2618 " dots nor does not start with a dot."
2619 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002620 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002621 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002622 }
2623
2624 err = invalid_domainchar(args[cur_arg + 1]);
2625 if (err) {
2626 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2627 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002630 }
2631
Willy Tarreau68a897b2009-12-03 23:28:34 +01002632 if (!curproxy->cookie_domain) {
2633 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2634 } else {
2635 /* one domain was already specified, add another one by
2636 * building the string which will be returned along with
2637 * the cookie.
2638 */
2639 char *new_ptr;
2640 int new_len = strlen(curproxy->cookie_domain) +
2641 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2642 new_ptr = malloc(new_len);
2643 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2644 free(curproxy->cookie_domain);
2645 curproxy->cookie_domain = new_ptr;
2646 }
Willy Tarreau31936852010-10-06 16:59:56 +02002647 cur_arg++;
2648 }
2649 else if (!strcmp(args[cur_arg], "maxidle")) {
2650 unsigned int maxidle;
2651 const char *res;
2652
2653 if (!*args[cur_arg + 1]) {
2654 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2655 file, linenum, args[cur_arg]);
2656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
2658 }
2659
2660 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2661 if (res) {
2662 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2663 file, linenum, *res, args[cur_arg]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667 curproxy->cookie_maxidle = maxidle;
2668 cur_arg++;
2669 }
2670 else if (!strcmp(args[cur_arg], "maxlife")) {
2671 unsigned int maxlife;
2672 const char *res;
2673
2674 if (!*args[cur_arg + 1]) {
2675 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2676 file, linenum, args[cur_arg]);
2677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680
2681 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2682 if (res) {
2683 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2684 file, linenum, *res, args[cur_arg]);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002689 cur_arg++;
2690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002692 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 +02002693 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 }
2697 cur_arg++;
2698 }
Willy Tarreau67402132012-05-31 20:40:20 +02002699 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2701 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 }
2704
Willy Tarreau67402132012-05-31 20:40:20 +02002705 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2707 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002710
Willy Tarreau67402132012-05-31 20:40:20 +02002711 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002712 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2713 file, linenum);
2714 err_code |= ERR_ALERT | ERR_FATAL;
2715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002717 else if (!strcmp(args[0], "persist")) { /* persist */
2718 if (*(args[1]) == 0) {
2719 Alert("parsing [%s:%d] : missing persist method.\n",
2720 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002723 }
2724
2725 if (!strncmp(args[1], "rdp-cookie", 10)) {
2726 curproxy->options2 |= PR_O2_RDPC_PRST;
2727
Emeric Brunb982a3d2010-01-04 15:45:53 +01002728 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002729 const char *beg, *end;
2730
2731 beg = args[1] + 11;
2732 end = strchr(beg, ')');
2733
2734 if (!end || end == beg) {
2735 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2736 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002739 }
2740
2741 free(curproxy->rdp_cookie_name);
2742 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2743 curproxy->rdp_cookie_len = end-beg;
2744 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002745 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002746 free(curproxy->rdp_cookie_name);
2747 curproxy->rdp_cookie_name = strdup("msts");
2748 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2749 }
2750 else { /* syntax */
2751 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2752 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002755 }
2756 }
2757 else {
2758 Alert("parsing [%s:%d] : unknown persist method.\n",
2759 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002760 err_code |= ERR_ALERT | ERR_FATAL;
2761 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002762 }
2763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002765 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002767 if (curproxy == &defproxy) {
2768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
Willy Tarreau977b8e42006-12-29 14:19:17 +01002773 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002777 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
2782 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002783 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 curproxy->appsession_name = strdup(args[1]);
2785 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2786 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002787 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2788 if (err) {
2789 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2790 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002793 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002794 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002795
Willy Tarreau51041c72007-09-09 21:56:53 +02002796 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2797 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002798 err_code |= ERR_ALERT | ERR_ABORT;
2799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002801
2802 cur_arg = 6;
2803 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002804 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2805 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002806 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002807 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002808 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002809 } else if (!strcmp(args[cur_arg], "prefix")) {
2810 curproxy->options2 |= PR_O2_AS_PFX;
2811 } else if (!strcmp(args[cur_arg], "mode")) {
2812 if (!*args[cur_arg + 1]) {
2813 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2814 file, linenum, args[0], args[cur_arg]);
2815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
2817 }
2818
2819 cur_arg++;
2820 if (!strcmp(args[cur_arg], "query-string")) {
2821 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2822 curproxy->options2 |= PR_O2_AS_M_QS;
2823 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2824 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2825 curproxy->options2 |= PR_O2_AS_M_PP;
2826 } else {
2827 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
2831 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002832 cur_arg++;
2833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 } /* Url App Session */
2835 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002836 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002837 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002838
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002840 if (curproxy == &defproxy) {
2841 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
2845
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 if (*(args[4]) == 0) {
2847 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2848 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002852 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 curproxy->capture_name = strdup(args[2]);
2854 curproxy->capture_namelen = strlen(curproxy->capture_name);
2855 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856 curproxy->to_log |= LW_COOKIE;
2857 }
2858 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2859 struct cap_hdr *hdr;
2860
2861 if (curproxy == &defproxy) {
2862 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 +02002863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 }
2866
2867 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2868 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2869 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 }
2873
2874 hdr = calloc(sizeof(struct cap_hdr), 1);
2875 hdr->next = curproxy->req_cap;
2876 hdr->name = strdup(args[3]);
2877 hdr->namelen = strlen(args[3]);
2878 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002879 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 hdr->index = curproxy->nb_req_cap++;
2881 curproxy->req_cap = hdr;
2882 curproxy->to_log |= LW_REQHDR;
2883 }
2884 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2885 struct cap_hdr *hdr;
2886
2887 if (curproxy == &defproxy) {
2888 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 +02002889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 }
2892
2893 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2894 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2895 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 }
2899 hdr = calloc(sizeof(struct cap_hdr), 1);
2900 hdr->next = curproxy->rsp_cap;
2901 hdr->name = strdup(args[3]);
2902 hdr->namelen = strlen(args[3]);
2903 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002904 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 hdr->index = curproxy->nb_rsp_cap++;
2906 curproxy->rsp_cap = hdr;
2907 curproxy->to_log |= LW_RSPHDR;
2908 }
2909 else {
2910 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002919
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 if (*(args[1]) == 0) {
2921 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
2926 curproxy->conn_retries = atol(args[1]);
2927 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002928 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002929 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002930
2931 if (curproxy == &defproxy) {
2932 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936
Willy Tarreau20b0de52012-12-24 15:45:22 +01002937 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2938 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2939 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2940 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002941 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002942 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2943 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 +01002944 file, linenum, args[0]);
2945 err_code |= ERR_WARN;
2946 }
2947
Willy Tarreauff011f22011-01-06 17:51:27 +01002948 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002949
Willy Tarreauff011f22011-01-06 17:51:27 +01002950 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002951 err_code |= ERR_ALERT | ERR_ABORT;
2952 goto out;
2953 }
2954
Willy Tarreau5002f572014-04-23 01:32:02 +02002955 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002956 err_code |= warnif_cond_conflicts(rule->cond,
2957 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2958 file, linenum);
2959
Willy Tarreauff011f22011-01-06 17:51:27 +01002960 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002961 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002962 else if (!strcmp(args[0], "http-response")) { /* response access control */
2963 struct http_res_rule *rule;
2964
2965 if (curproxy == &defproxy) {
2966 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970
2971 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2972 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2973 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2974 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2975 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2976 file, linenum, args[0]);
2977 err_code |= ERR_WARN;
2978 }
2979
2980 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2981
2982 if (!rule) {
2983 err_code |= ERR_ALERT | ERR_ABORT;
2984 goto out;
2985 }
2986
2987 err_code |= warnif_cond_conflicts(rule->cond,
2988 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2989 file, linenum);
2990
2991 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2992 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002993 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2994 /* set the header name and length into the proxy structure */
2995 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2996 err_code |= ERR_WARN;
2997
2998 if (!*args[1]) {
2999 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3000 file, linenum, args[0]);
3001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
3003 }
3004
3005 /* set the desired header name */
3006 free(curproxy->server_id_hdr_name);
3007 curproxy->server_id_hdr_name = strdup(args[1]);
3008 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3009 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003010 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003011 struct http_req_rule *rule;
3012
Willy Tarreaub099aca2008-10-12 17:26:37 +02003013 if (curproxy == &defproxy) {
3014 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003017 }
3018
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003019 /* emulate "block" using "http-request block". Since these rules are supposed to
3020 * be processed before all http-request rules, we put them into their own list
3021 * and will insert them at the end.
3022 */
3023 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3024 if (!rule) {
3025 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003026 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003027 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003028 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3029 err_code |= warnif_cond_conflicts(rule->cond,
3030 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3031 file, linenum);
3032 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003033
3034 if (!already_warned(WARN_BLOCK_DEPRECATED))
3035 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]);
3036
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003037 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003038 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003039 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003040
Cyril Bonté99ed3272010-01-24 23:29:44 +01003041 if (curproxy == &defproxy) {
3042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003047 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003048 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3049 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003052 }
3053
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003054 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003055 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003056 err_code |= warnif_cond_conflicts(rule->cond,
3057 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3058 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003059 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003060 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003061 struct switching_rule *rule;
3062
Willy Tarreaub099aca2008-10-12 17:26:37 +02003063 if (curproxy == &defproxy) {
3064 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003067 }
3068
Willy Tarreau55ea7572007-06-17 19:56:27 +02003069 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003071
3072 if (*(args[1]) == 0) {
3073 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003076 }
3077
Willy Tarreauf51658d2014-04-23 01:21:56 +02003078 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3079 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3080 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3081 file, linenum, errmsg);
3082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003085
Willy Tarreauf51658d2014-04-23 01:21:56 +02003086 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003087 }
3088
3089 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3090 rule->cond = cond;
3091 rule->be.name = strdup(args[1]);
3092 LIST_INIT(&rule->list);
3093 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3094 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003095 else if (strcmp(args[0], "use-server") == 0) {
3096 struct server_rule *rule;
3097
3098 if (curproxy == &defproxy) {
3099 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103
3104 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3105 err_code |= ERR_WARN;
3106
3107 if (*(args[1]) == 0) {
3108 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
3112
3113 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3114 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3115 file, linenum, args[0]);
3116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003120 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3121 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3122 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
3126
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003127 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003128
3129 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3130 rule->cond = cond;
3131 rule->srv.name = strdup(args[1]);
3132 LIST_INIT(&rule->list);
3133 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3134 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3135 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003136 else if ((!strcmp(args[0], "force-persist")) ||
3137 (!strcmp(args[0], "ignore-persist"))) {
3138 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003139
3140 if (curproxy == &defproxy) {
3141 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
3146 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3147 err_code |= ERR_WARN;
3148
Willy Tarreauef6494c2010-01-28 17:12:36 +01003149 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003150 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3151 file, linenum, args[0]);
3152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
3154 }
3155
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003156 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3157 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3158 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003159 err_code |= ERR_ALERT | ERR_FATAL;
3160 goto out;
3161 }
3162
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003163 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3164 * where force-persist is applied.
3165 */
3166 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003167
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003168 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003169 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003170 if (!strcmp(args[0], "force-persist")) {
3171 rule->type = PERSIST_TYPE_FORCE;
3172 } else {
3173 rule->type = PERSIST_TYPE_IGNORE;
3174 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003175 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003176 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003177 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003178 else if (!strcmp(args[0], "stick-table")) {
3179 int myidx = 1;
3180
Emeric Brun32da3c42010-09-23 18:39:19 +02003181 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003182 curproxy->table.type = (unsigned int)-1;
3183 while (*args[myidx]) {
3184 const char *err;
3185
3186 if (strcmp(args[myidx], "size") == 0) {
3187 myidx++;
3188 if (!*(args[myidx])) {
3189 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3190 file, linenum, args[myidx-1]);
3191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
3193 }
3194 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3195 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3196 file, linenum, *err, args[myidx-1]);
3197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
3199 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003200 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003201 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003202 else if (strcmp(args[myidx], "peers") == 0) {
3203 myidx++;
Godbach50523162013-12-11 19:48:57 +08003204 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003205 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3206 file, linenum, args[myidx-1]);
3207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Godbach50523162013-12-11 19:48:57 +08003209 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003210 curproxy->table.peers.name = strdup(args[myidx++]);
3211 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003212 else if (strcmp(args[myidx], "expire") == 0) {
3213 myidx++;
3214 if (!*(args[myidx])) {
3215 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3216 file, linenum, args[myidx-1]);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
3219 }
3220 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3221 if (err) {
3222 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3223 file, linenum, *err, args[myidx-1]);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
3227 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003228 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003229 }
3230 else if (strcmp(args[myidx], "nopurge") == 0) {
3231 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003232 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 }
3234 else if (strcmp(args[myidx], "type") == 0) {
3235 myidx++;
3236 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3237 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3238 file, linenum, args[myidx]);
3239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
3241 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003242 /* myidx already points to next arg */
3243 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003244 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003245 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003246 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003247
3248 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003249 nw = args[myidx];
3250 while (*nw) {
3251 /* the "store" keyword supports a comma-separated list */
3252 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003253 sa = NULL; /* store arg */
3254 while (*nw && *nw != ',') {
3255 if (*nw == '(') {
3256 *nw = 0;
3257 sa = ++nw;
3258 while (*nw != ')') {
3259 if (!*nw) {
3260 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3261 file, linenum, args[0], cw);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265 nw++;
3266 }
3267 *nw = '\0';
3268 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003269 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003270 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003271 if (*nw)
3272 *nw++ = '\0';
3273 type = stktable_get_data_type(cw);
3274 if (type < 0) {
3275 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3276 file, linenum, args[0], cw);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
Willy Tarreauac782882010-06-20 10:41:54 +02003280
3281 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3282 switch (err) {
3283 case PE_NONE: break;
3284 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003285 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3286 file, linenum, args[0], cw);
3287 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003288 break;
3289
3290 case PE_ARG_MISSING:
3291 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3292 file, linenum, args[0], cw);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295
3296 case PE_ARG_NOT_USED:
3297 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3298 file, linenum, args[0], cw);
3299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
3301
3302 default:
3303 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3304 file, linenum, args[0], cw);
3305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003307 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003308 }
3309 myidx++;
3310 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003311 else {
3312 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3313 file, linenum, args[myidx]);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003316 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003317 }
3318
3319 if (!curproxy->table.size) {
3320 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3321 file, linenum);
3322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
3324 }
3325
3326 if (curproxy->table.type == (unsigned int)-1) {
3327 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3328 file, linenum);
3329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
3331 }
3332 }
3333 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003334 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003335 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003336 int myidx = 0;
3337 const char *name = NULL;
3338 int flags;
3339
3340 if (curproxy == &defproxy) {
3341 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
3344 }
3345
3346 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3347 err_code |= ERR_WARN;
3348 goto out;
3349 }
3350
3351 myidx++;
3352 if ((strcmp(args[myidx], "store") == 0) ||
3353 (strcmp(args[myidx], "store-request") == 0)) {
3354 myidx++;
3355 flags = STK_IS_STORE;
3356 }
3357 else if (strcmp(args[myidx], "store-response") == 0) {
3358 myidx++;
3359 flags = STK_IS_STORE | STK_ON_RSP;
3360 }
3361 else if (strcmp(args[myidx], "match") == 0) {
3362 myidx++;
3363 flags = STK_IS_MATCH;
3364 }
3365 else if (strcmp(args[myidx], "on") == 0) {
3366 myidx++;
3367 flags = STK_IS_MATCH | STK_IS_STORE;
3368 }
3369 else {
3370 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374
3375 if (*(args[myidx]) == 0) {
3376 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003381 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003382 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003383 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003384 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388
3389 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003390 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3391 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3392 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003393 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003394 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003395 goto out;
3396 }
3397 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003398 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3399 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3400 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003401 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003402 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003403 goto out;
3404 }
3405 }
3406
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003407 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003408 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003409
Emeric Brunb982a3d2010-01-04 15:45:53 +01003410 if (strcmp(args[myidx], "table") == 0) {
3411 myidx++;
3412 name = args[myidx++];
3413 }
3414
Willy Tarreauef6494c2010-01-28 17:12:36 +01003415 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003416 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3417 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3418 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003419 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003420 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003421 goto out;
3422 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003423 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003424 else if (*(args[myidx])) {
3425 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3426 file, linenum, args[0], args[myidx]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003428 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003429 goto out;
3430 }
Emeric Brun97679e72010-09-23 17:56:44 +02003431 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003432 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003433 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003434 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003435
Emeric Brunb982a3d2010-01-04 15:45:53 +01003436 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3437 rule->cond = cond;
3438 rule->expr = expr;
3439 rule->flags = flags;
3440 rule->table.name = name ? strdup(name) : NULL;
3441 LIST_INIT(&rule->list);
3442 if (flags & STK_ON_RSP)
3443 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3444 else
3445 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 else if (!strcmp(args[0], "stats")) {
3448 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3449 curproxy->uri_auth = NULL; /* we must detach from the default config */
3450
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003451 if (!*args[1]) {
3452 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003453 } else if (!strcmp(args[1], "admin")) {
3454 struct stats_admin_rule *rule;
3455
3456 if (curproxy == &defproxy) {
3457 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
3460 }
3461
3462 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3463 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3464 err_code |= ERR_ALERT | ERR_ABORT;
3465 goto out;
3466 }
3467
3468 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3469 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3470 file, linenum, args[0], args[1]);
3471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
3473 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003474 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3475 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3476 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003481 err_code |= warnif_cond_conflicts(cond,
3482 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3483 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003484
3485 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3486 rule->cond = cond;
3487 LIST_INIT(&rule->list);
3488 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 } else if (!strcmp(args[1], "uri")) {
3490 if (*(args[2]) == 0) {
3491 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3495 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_ABORT;
3497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 }
3499 } else if (!strcmp(args[1], "realm")) {
3500 if (*(args[2]) == 0) {
3501 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3505 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_ABORT;
3507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003509 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003510 unsigned interval;
3511
3512 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3513 if (err) {
3514 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3515 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003518 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3519 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_ABORT;
3521 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003522 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003523 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003524 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003525
3526 if (curproxy == &defproxy) {
3527 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531
3532 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3533 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3534 err_code |= ERR_ALERT | ERR_ABORT;
3535 goto out;
3536 }
3537
Willy Tarreauff011f22011-01-06 17:51:27 +01003538 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3539 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003540 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3541 file, linenum, args[0]);
3542 err_code |= ERR_WARN;
3543 }
3544
Willy Tarreauff011f22011-01-06 17:51:27 +01003545 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003546
Willy Tarreauff011f22011-01-06 17:51:27 +01003547 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003548 err_code |= ERR_ALERT | ERR_ABORT;
3549 goto out;
3550 }
3551
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003552 err_code |= warnif_cond_conflicts(rule->cond,
3553 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3554 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003555 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003556
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 } else if (!strcmp(args[1], "auth")) {
3558 if (*(args[2]) == 0) {
3559 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3563 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_ABORT;
3565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 }
3567 } else if (!strcmp(args[1], "scope")) {
3568 if (*(args[2]) == 0) {
3569 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3573 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_ABORT;
3575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 }
3577 } else if (!strcmp(args[1], "enable")) {
3578 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3579 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_ABORT;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003583 } else if (!strcmp(args[1], "hide-version")) {
3584 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3585 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_ABORT;
3587 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003588 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003589 } else if (!strcmp(args[1], "show-legends")) {
3590 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3591 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3592 err_code |= ERR_ALERT | ERR_ABORT;
3593 goto out;
3594 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003595 } else if (!strcmp(args[1], "show-node")) {
3596
3597 if (*args[2]) {
3598 int i;
3599 char c;
3600
3601 for (i=0; args[2][i]; i++) {
3602 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003603 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3604 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003605 break;
3606 }
3607
3608 if (!i || args[2][i]) {
3609 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3610 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3611 file, linenum, args[0], args[1]);
3612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
3614 }
3615 }
3616
3617 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3618 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3619 err_code |= ERR_ALERT | ERR_ABORT;
3620 goto out;
3621 }
3622 } else if (!strcmp(args[1], "show-desc")) {
3623 char *desc = NULL;
3624
3625 if (*args[2]) {
3626 int i, len=0;
3627 char *d;
3628
Willy Tarreau348acfe2014-04-14 15:00:39 +02003629 for (i = 2; *args[i]; i++)
3630 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003631
3632 desc = d = (char *)calloc(1, len);
3633
Willy Tarreau348acfe2014-04-14 15:00:39 +02003634 d += snprintf(d, desc + len - d, "%s", args[2]);
3635 for (i = 3; *args[i]; i++)
3636 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003637 }
3638
3639 if (!*args[2] && !global.desc)
3640 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3641 file, linenum, args[1]);
3642 else {
3643 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3644 free(desc);
3645 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3646 err_code |= ERR_ALERT | ERR_ABORT;
3647 goto out;
3648 }
3649 free(desc);
3650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003652stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003653 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 +01003654 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 }
3658 }
3659 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003660 int optnum;
3661
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003662 if (*(args[1]) == '\0') {
3663 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3664 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003668
3669 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3670 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003671 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3672 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3673 file, linenum, cfg_opts[optnum].name);
3674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
3676 }
Willy Tarreau93893792009-07-23 13:19:11 +02003677 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3678 err_code |= ERR_WARN;
3679 goto out;
3680 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003681
Willy Tarreau3842f002009-06-14 11:39:52 +02003682 curproxy->no_options &= ~cfg_opts[optnum].val;
3683 curproxy->options &= ~cfg_opts[optnum].val;
3684
3685 switch (kwm) {
3686 case KWM_STD:
3687 curproxy->options |= cfg_opts[optnum].val;
3688 break;
3689 case KWM_NO:
3690 curproxy->no_options |= cfg_opts[optnum].val;
3691 break;
3692 case KWM_DEF: /* already cleared */
3693 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003694 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003695
Willy Tarreau93893792009-07-23 13:19:11 +02003696 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003697 }
3698 }
3699
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003700 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3701 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003702 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3703 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3704 file, linenum, cfg_opts2[optnum].name);
3705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
3707 }
Willy Tarreau93893792009-07-23 13:19:11 +02003708 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3709 err_code |= ERR_WARN;
3710 goto out;
3711 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003712
Willy Tarreau3842f002009-06-14 11:39:52 +02003713 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3714 curproxy->options2 &= ~cfg_opts2[optnum].val;
3715
3716 switch (kwm) {
3717 case KWM_STD:
3718 curproxy->options2 |= cfg_opts2[optnum].val;
3719 break;
3720 case KWM_NO:
3721 curproxy->no_options2 |= cfg_opts2[optnum].val;
3722 break;
3723 case KWM_DEF: /* already cleared */
3724 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003725 }
Willy Tarreau93893792009-07-23 13:19:11 +02003726 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003727 }
3728 }
3729
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003730 /* HTTP options override each other. They can be cancelled using
3731 * "no option xxx" which only switches to default mode if the mode
3732 * was this one (useful for cancelling options set in defaults
3733 * sections).
3734 */
3735 if (strcmp(args[1], "httpclose") == 0) {
3736 if (kwm == KWM_STD) {
3737 curproxy->options &= ~PR_O_HTTP_MODE;
3738 curproxy->options |= PR_O_HTTP_PCL;
3739 goto out;
3740 }
3741 else if (kwm == KWM_NO) {
3742 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3743 curproxy->options &= ~PR_O_HTTP_MODE;
3744 goto out;
3745 }
3746 }
3747 else if (strcmp(args[1], "forceclose") == 0) {
3748 if (kwm == KWM_STD) {
3749 curproxy->options &= ~PR_O_HTTP_MODE;
3750 curproxy->options |= PR_O_HTTP_FCL;
3751 goto out;
3752 }
3753 else if (kwm == KWM_NO) {
3754 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3755 curproxy->options &= ~PR_O_HTTP_MODE;
3756 goto out;
3757 }
3758 }
3759 else if (strcmp(args[1], "http-server-close") == 0) {
3760 if (kwm == KWM_STD) {
3761 curproxy->options &= ~PR_O_HTTP_MODE;
3762 curproxy->options |= PR_O_HTTP_SCL;
3763 goto out;
3764 }
3765 else if (kwm == KWM_NO) {
3766 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3767 curproxy->options &= ~PR_O_HTTP_MODE;
3768 goto out;
3769 }
3770 }
3771 else if (strcmp(args[1], "http-keep-alive") == 0) {
3772 if (kwm == KWM_STD) {
3773 curproxy->options &= ~PR_O_HTTP_MODE;
3774 curproxy->options |= PR_O_HTTP_KAL;
3775 goto out;
3776 }
3777 else if (kwm == KWM_NO) {
3778 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3779 curproxy->options &= ~PR_O_HTTP_MODE;
3780 goto out;
3781 }
3782 }
3783 else if (strcmp(args[1], "http-tunnel") == 0) {
3784 if (kwm == KWM_STD) {
3785 curproxy->options &= ~PR_O_HTTP_MODE;
3786 curproxy->options |= PR_O_HTTP_TUN;
3787 goto out;
3788 }
3789 else if (kwm == KWM_NO) {
3790 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3791 curproxy->options &= ~PR_O_HTTP_MODE;
3792 goto out;
3793 }
3794 }
3795
Willy Tarreau3842f002009-06-14 11:39:52 +02003796 if (kwm != KWM_STD) {
3797 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003798 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003801 }
3802
Emeric Brun3a058f32009-06-30 18:26:00 +02003803 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003804 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003806 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003807 if (*(args[2]) != '\0') {
3808 if (!strcmp(args[2], "clf")) {
3809 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003810 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003811 } else {
William Lallemand629b1c02015-05-28 18:02:48 +02003812 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003815 }
3816 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003817 if (curproxy->conf.logformat_string != default_http_log_format &&
3818 curproxy->conf.logformat_string != default_tcp_log_format &&
3819 curproxy->conf.logformat_string != clf_http_log_format)
3820 free(curproxy->conf.logformat_string);
3821 curproxy->conf.logformat_string = logformat;
3822
3823 free(curproxy->conf.lfs_file);
3824 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3825 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003826 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003827 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003829 if (curproxy->conf.logformat_string != default_http_log_format &&
3830 curproxy->conf.logformat_string != default_tcp_log_format &&
3831 curproxy->conf.logformat_string != clf_http_log_format)
3832 free(curproxy->conf.logformat_string);
3833 curproxy->conf.logformat_string = default_tcp_log_format;
3834
3835 free(curproxy->conf.lfs_file);
3836 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3837 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 else if (!strcmp(args[1], "tcpka")) {
3840 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003841 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003843
3844 if (curproxy->cap & PR_CAP_FE)
3845 curproxy->options |= PR_O_TCP_CLI_KA;
3846 if (curproxy->cap & PR_CAP_BE)
3847 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
3849 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_WARN;
3852
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003854 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003855 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003856 curproxy->options2 &= ~PR_O2_CHK_ANY;
3857 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 if (!*args[2]) { /* no argument */
3859 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3860 curproxy->check_len = strlen(DEF_CHECK_REQ);
3861 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003862 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 curproxy->check_req = (char *)malloc(reqlen);
3864 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003865 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003867 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 if (*args[4])
3869 reqlen += strlen(args[4]);
3870 else
3871 reqlen += strlen("HTTP/1.0");
3872
3873 curproxy->check_req = (char *)malloc(reqlen);
3874 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003875 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003877 }
3878 else if (!strcmp(args[1], "ssl-hello-chk")) {
3879 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003880 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003882
Willy Tarreaua534fea2008-08-03 12:19:50 +02003883 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003884 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003885 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003886 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 }
Willy Tarreau23677902007-05-08 23:50:35 +02003888 else if (!strcmp(args[1], "smtpchk")) {
3889 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003890 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003891 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003892 curproxy->options2 &= ~PR_O2_CHK_ANY;
3893 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003894
3895 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3896 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3897 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3898 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3899 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3900 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3901 curproxy->check_req = (char *)malloc(reqlen);
3902 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3903 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3904 } else {
3905 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3906 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3907 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3908 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3909 }
3910 }
3911 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003912 else if (!strcmp(args[1], "pgsql-check")) {
3913 /* use PostgreSQL request to check servers' health */
3914 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3915 err_code |= ERR_WARN;
3916
3917 free(curproxy->check_req);
3918 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003919 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003920 curproxy->options2 |= PR_O2_PGSQL_CHK;
3921
3922 if (*(args[2])) {
3923 int cur_arg = 2;
3924
3925 while (*(args[cur_arg])) {
3926 if (strcmp(args[cur_arg], "user") == 0) {
3927 char * packet;
3928 uint32_t packet_len;
3929 uint32_t pv;
3930
3931 /* suboption header - needs additional argument for it */
3932 if (*(args[cur_arg+1]) == 0) {
3933 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3934 file, linenum, args[0], args[1], args[cur_arg]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938
3939 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3940 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3941 pv = htonl(0x30000); /* protocol version 3.0 */
3942
3943 packet = (char*) calloc(1, packet_len);
3944
3945 memcpy(packet + 4, &pv, 4);
3946
3947 /* copy "user" */
3948 memcpy(packet + 8, "user", 4);
3949
3950 /* copy username */
3951 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3952
3953 free(curproxy->check_req);
3954 curproxy->check_req = packet;
3955 curproxy->check_len = packet_len;
3956
3957 packet_len = htonl(packet_len);
3958 memcpy(packet, &packet_len, 4);
3959 cur_arg += 2;
3960 } else {
3961 /* unknown suboption - catchall */
3962 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3963 file, linenum, args[0], args[1]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967 } /* end while loop */
3968 }
3969 }
3970
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003971 else if (!strcmp(args[1], "redis-check")) {
3972 /* use REDIS PING request to check servers' health */
3973 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3974 err_code |= ERR_WARN;
3975
3976 free(curproxy->check_req);
3977 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003978 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003979 curproxy->options2 |= PR_O2_REDIS_CHK;
3980
3981 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3982 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3983 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3984 }
3985
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003986 else if (!strcmp(args[1], "mysql-check")) {
3987 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003988 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3989 err_code |= ERR_WARN;
3990
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003991 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003992 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003993 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003994 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003995
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003996 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003997 * const char mysql40_client_auth_pkt[] = {
3998 * "\x0e\x00\x00" // packet length
3999 * "\x01" // packet number
4000 * "\x00\x00" // client capabilities
4001 * "\x00\x00\x01" // max packet
4002 * "haproxy\x00" // username (null terminated string)
4003 * "\x00" // filler (always 0x00)
4004 * "\x01\x00\x00" // packet length
4005 * "\x00" // packet number
4006 * "\x01" // COM_QUIT command
4007 * };
4008 */
4009
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004010 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4011 * const char mysql41_client_auth_pkt[] = {
4012 * "\x0e\x00\x00\" // packet length
4013 * "\x01" // packet number
4014 * "\x00\x00\x00\x00" // client capabilities
4015 * "\x00\x00\x00\x01" // max packet
4016 * "\x21" // character set (UTF-8)
4017 * char[23] // All zeroes
4018 * "haproxy\x00" // username (null terminated string)
4019 * "\x00" // filler (always 0x00)
4020 * "\x01\x00\x00" // packet length
4021 * "\x00" // packet number
4022 * "\x01" // COM_QUIT command
4023 * };
4024 */
4025
4026
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004027 if (*(args[2])) {
4028 int cur_arg = 2;
4029
4030 while (*(args[cur_arg])) {
4031 if (strcmp(args[cur_arg], "user") == 0) {
4032 char *mysqluser;
4033 int packetlen, reqlen, userlen;
4034
4035 /* suboption header - needs additional argument for it */
4036 if (*(args[cur_arg+1]) == 0) {
4037 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4038 file, linenum, args[0], args[1], args[cur_arg]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042 mysqluser = args[cur_arg + 1];
4043 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004044
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004045 if (*(args[cur_arg+2])) {
4046 if (!strcmp(args[cur_arg+2], "post-41")) {
4047 packetlen = userlen + 7 + 27;
4048 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004049
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004050 free(curproxy->check_req);
4051 curproxy->check_req = (char *)calloc(1, reqlen);
4052 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004053
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004054 snprintf(curproxy->check_req, 4, "%c%c%c",
4055 ((unsigned char) packetlen & 0xff),
4056 ((unsigned char) (packetlen >> 8) & 0xff),
4057 ((unsigned char) (packetlen >> 16) & 0xff));
4058
4059 curproxy->check_req[3] = 1;
4060 curproxy->check_req[5] = 130;
4061 curproxy->check_req[11] = 1;
4062 curproxy->check_req[12] = 33;
4063 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4064 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4065 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4066 cur_arg += 3;
4067 } else {
4068 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072 } else {
4073 packetlen = userlen + 7;
4074 reqlen = packetlen + 9;
4075
4076 free(curproxy->check_req);
4077 curproxy->check_req = (char *)calloc(1, reqlen);
4078 curproxy->check_len = reqlen;
4079
4080 snprintf(curproxy->check_req, 4, "%c%c%c",
4081 ((unsigned char) packetlen & 0xff),
4082 ((unsigned char) (packetlen >> 8) & 0xff),
4083 ((unsigned char) (packetlen >> 16) & 0xff));
4084
4085 curproxy->check_req[3] = 1;
4086 curproxy->check_req[5] = 128;
4087 curproxy->check_req[8] = 1;
4088 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4089 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4090 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4091 cur_arg += 2;
4092 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004093 } else {
4094 /* unknown suboption - catchall */
4095 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4096 file, linenum, args[0], args[1]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
4100 } /* end while loop */
4101 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004102 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004103 else if (!strcmp(args[1], "ldap-check")) {
4104 /* use LDAP request to check servers' health */
4105 free(curproxy->check_req);
4106 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004107 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004108 curproxy->options2 |= PR_O2_LDAP_CHK;
4109
4110 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4111 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4112 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4113 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004114 else if (!strcmp(args[1], "tcp-check")) {
4115 /* use raw TCPCHK send/expect to check servers' health */
4116 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4117 err_code |= ERR_WARN;
4118
4119 free(curproxy->check_req);
4120 curproxy->check_req = NULL;
4121 curproxy->options2 &= ~PR_O2_CHK_ANY;
4122 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4123 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004124 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004125 int cur_arg;
4126
4127 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4128 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004129 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004130
Willy Tarreau87cf5142011-08-19 22:57:24 +02004131 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004132
4133 free(curproxy->fwdfor_hdr_name);
4134 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4135 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4136
4137 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4138 cur_arg = 2;
4139 while (*(args[cur_arg])) {
4140 if (!strcmp(args[cur_arg], "except")) {
4141 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004142 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004143 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4144 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004147 }
4148 /* flush useless bits */
4149 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004150 cur_arg += 2;
4151 } else if (!strcmp(args[cur_arg], "header")) {
4152 /* suboption header - needs additional argument for it */
4153 if (*(args[cur_arg+1]) == 0) {
4154 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4155 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004158 }
4159 free(curproxy->fwdfor_hdr_name);
4160 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4161 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4162 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004163 } else if (!strcmp(args[cur_arg], "if-none")) {
4164 curproxy->options &= ~PR_O_FF_ALWAYS;
4165 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004166 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004167 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004168 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004169 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004172 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004173 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004174 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004175 else if (!strcmp(args[1], "originalto")) {
4176 int cur_arg;
4177
4178 /* insert x-original-to field, but not for the IP address listed as an except.
4179 * set default options (ie: bitfield, header name, etc)
4180 */
4181
4182 curproxy->options |= PR_O_ORGTO;
4183
4184 free(curproxy->orgto_hdr_name);
4185 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4186 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4187
Willy Tarreau87cf5142011-08-19 22:57:24 +02004188 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004189 cur_arg = 2;
4190 while (*(args[cur_arg])) {
4191 if (!strcmp(args[cur_arg], "except")) {
4192 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004193 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 +02004194 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4195 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004198 }
4199 /* flush useless bits */
4200 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4201 cur_arg += 2;
4202 } else if (!strcmp(args[cur_arg], "header")) {
4203 /* suboption header - needs additional argument for it */
4204 if (*(args[cur_arg+1]) == 0) {
4205 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4206 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004209 }
4210 free(curproxy->orgto_hdr_name);
4211 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4212 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4213 cur_arg += 2;
4214 } else {
4215 /* unknown suboption - catchall */
4216 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4217 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004220 }
4221 } /* end while loop */
4222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 else {
4224 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 }
Willy Tarreau93893792009-07-23 13:19:11 +02004228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004230 else if (!strcmp(args[0], "default_backend")) {
4231 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004233
4234 if (*(args[1]) == 0) {
4235 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004238 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004239 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004240 curproxy->defbe.name = strdup(args[1]);
4241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004245
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004246 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4247 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 +01004248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 /* enable reconnections to dispatch */
4251 curproxy->options |= PR_O_REDISP;
4252 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004253 else if (!strcmp(args[0], "http-check")) {
4254 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004256
4257 if (strcmp(args[1], "disable-on-404") == 0) {
4258 /* enable a graceful server shutdown on an HTTP 404 response */
4259 curproxy->options |= PR_O_DISABLE404;
4260 }
Willy Tarreauef781042010-01-27 11:53:01 +01004261 else if (strcmp(args[1], "send-state") == 0) {
4262 /* enable emission of the apparent state of a server in HTTP checks */
4263 curproxy->options2 |= PR_O2_CHK_SNDST;
4264 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004265 else if (strcmp(args[1], "expect") == 0) {
4266 const char *ptr_arg;
4267 int cur_arg;
4268
4269 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4270 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
4273 }
4274
4275 cur_arg = 2;
4276 /* consider exclamation marks, sole or at the beginning of a word */
4277 while (*(ptr_arg = args[cur_arg])) {
4278 while (*ptr_arg == '!') {
4279 curproxy->options2 ^= PR_O2_EXP_INV;
4280 ptr_arg++;
4281 }
4282 if (*ptr_arg)
4283 break;
4284 cur_arg++;
4285 }
4286 /* now ptr_arg points to the beginning of a word past any possible
4287 * exclamation mark, and cur_arg is the argument which holds this word.
4288 */
4289 if (strcmp(ptr_arg, "status") == 0) {
4290 if (!*(args[cur_arg + 1])) {
4291 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4292 file, linenum, args[0], args[1], ptr_arg);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004297 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004298 curproxy->expect_str = strdup(args[cur_arg + 1]);
4299 }
4300 else if (strcmp(ptr_arg, "string") == 0) {
4301 if (!*(args[cur_arg + 1])) {
4302 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4303 file, linenum, args[0], args[1], ptr_arg);
4304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004308 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004309 curproxy->expect_str = strdup(args[cur_arg + 1]);
4310 }
4311 else if (strcmp(ptr_arg, "rstatus") == 0) {
4312 if (!*(args[cur_arg + 1])) {
4313 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4314 file, linenum, args[0], args[1], ptr_arg);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004319 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004320 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004321 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004322 free(curproxy->expect_regex);
4323 curproxy->expect_regex = NULL;
4324 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004325 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004326 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4327 error = NULL;
4328 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4329 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4330 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4331 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 }
4336 else if (strcmp(ptr_arg, "rstring") == 0) {
4337 if (!*(args[cur_arg + 1])) {
4338 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4339 file, linenum, args[0], args[1], ptr_arg);
4340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342 }
4343 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004344 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004345 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004346 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004347 free(curproxy->expect_regex);
4348 curproxy->expect_regex = NULL;
4349 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004350 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004351 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4352 error = NULL;
4353 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4354 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4355 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4356 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360 }
4361 else {
4362 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4363 file, linenum, args[0], args[1], ptr_arg);
4364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
4366 }
4367 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004368 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004369 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 +02004370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004372 }
4373 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004374 else if (!strcmp(args[0], "tcp-check")) {
4375 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4376 err_code |= ERR_WARN;
4377
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004378 if (strcmp(args[1], "connect") == 0) {
4379 const char *ptr_arg;
4380 int cur_arg;
4381 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004382
4383 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004384 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004385
Willy Tarreau5bff0592015-05-13 12:24:53 +02004386 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4387 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4388 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4389 file, linenum);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004392 }
4393
4394 cur_arg = 2;
4395 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4396 tcpcheck->action = TCPCHK_ACT_CONNECT;
4397
4398 /* parsing each parameters to fill up the rule */
4399 while (*(ptr_arg = args[cur_arg])) {
4400 /* tcp port */
4401 if (strcmp(args[cur_arg], "port") == 0) {
4402 if ( (atol(args[cur_arg + 1]) > 65535) ||
4403 (atol(args[cur_arg + 1]) < 1) ){
4404 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4405 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
4408 }
4409 tcpcheck->port = atol(args[cur_arg + 1]);
4410 cur_arg += 2;
4411 }
4412 /* send proxy protocol */
4413 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4414 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4415 cur_arg++;
4416 }
4417#ifdef USE_OPENSSL
4418 else if (strcmp(args[cur_arg], "ssl") == 0) {
4419 curproxy->options |= PR_O_TCPCHK_SSL;
4420 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4421 cur_arg++;
4422 }
4423#endif /* USE_OPENSSL */
4424 else {
4425#ifdef USE_OPENSSL
4426 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4427#else /* USE_OPENSSL */
4428 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4429#endif /* USE_OPENSSL */
4430 file, linenum, args[0], args[1], args[cur_arg]);
4431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
4434
4435 }
4436
4437 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4438 }
4439 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004440 if (! *(args[2]) ) {
4441 /* SEND string expected */
4442 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4443 file, linenum, args[0], args[1], args[2]);
4444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
4446 } else {
4447 struct tcpcheck_rule *tcpcheck;
4448
4449 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4450
4451 tcpcheck->action = TCPCHK_ACT_SEND;
4452 tcpcheck->string_len = strlen(args[2]);
4453 tcpcheck->string = strdup(args[2]);
4454 tcpcheck->expect_regex = NULL;
4455
4456 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4457 }
4458 }
4459 else if (strcmp(args[1], "send-binary") == 0) {
4460 if (! *(args[2]) ) {
4461 /* SEND binary string expected */
4462 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4463 file, linenum, args[0], args[1], args[2]);
4464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
4466 } else {
4467 struct tcpcheck_rule *tcpcheck;
4468 char *err = NULL;
4469
4470 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4471
4472 tcpcheck->action = TCPCHK_ACT_SEND;
4473 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4474 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4475 file, linenum, args[0], args[1], args[2], err);
4476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
4478 }
4479 tcpcheck->expect_regex = NULL;
4480
4481 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4482 }
4483 }
4484 else if (strcmp(args[1], "expect") == 0) {
4485 const char *ptr_arg;
4486 int cur_arg;
4487 int inverse = 0;
4488
4489 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4490 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
4494
4495 cur_arg = 2;
4496 /* consider exclamation marks, sole or at the beginning of a word */
4497 while (*(ptr_arg = args[cur_arg])) {
4498 while (*ptr_arg == '!') {
4499 inverse = !inverse;
4500 ptr_arg++;
4501 }
4502 if (*ptr_arg)
4503 break;
4504 cur_arg++;
4505 }
4506 /* now ptr_arg points to the beginning of a word past any possible
4507 * exclamation mark, and cur_arg is the argument which holds this word.
4508 */
4509 if (strcmp(ptr_arg, "binary") == 0) {
4510 if (!*(args[cur_arg + 1])) {
4511 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4512 file, linenum, args[0], args[1], ptr_arg);
4513 err_code |= ERR_ALERT | ERR_FATAL;
4514 goto out;
4515 }
4516 struct tcpcheck_rule *tcpcheck;
4517 char *err = NULL;
4518
4519 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4520
4521 tcpcheck->action = TCPCHK_ACT_EXPECT;
4522 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4523 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4524 file, linenum, args[0], args[1], args[2], err);
4525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
4527 }
4528 tcpcheck->expect_regex = NULL;
4529 tcpcheck->inverse = inverse;
4530
4531 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4532 }
4533 else if (strcmp(ptr_arg, "string") == 0) {
4534 if (!*(args[cur_arg + 1])) {
4535 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4536 file, linenum, args[0], args[1], ptr_arg);
4537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
4540 struct tcpcheck_rule *tcpcheck;
4541
4542 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4543
4544 tcpcheck->action = TCPCHK_ACT_EXPECT;
4545 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4546 tcpcheck->string = strdup(args[cur_arg + 1]);
4547 tcpcheck->expect_regex = NULL;
4548 tcpcheck->inverse = inverse;
4549
4550 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4551 }
4552 else if (strcmp(ptr_arg, "rstring") == 0) {
4553 if (!*(args[cur_arg + 1])) {
4554 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4555 file, linenum, args[0], args[1], ptr_arg);
4556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
4558 }
4559 struct tcpcheck_rule *tcpcheck;
4560
4561 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4562
4563 tcpcheck->action = TCPCHK_ACT_EXPECT;
4564 tcpcheck->string_len = 0;
4565 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004566 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4567 error = NULL;
4568 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4569 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4570 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4571 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
4574 }
4575 tcpcheck->inverse = inverse;
4576
4577 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4578 }
4579 else {
4580 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4581 file, linenum, args[0], args[1], ptr_arg);
4582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
4584 }
4585 }
4586 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004587 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
4590 }
4591 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004592 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004593 if (curproxy == &defproxy) {
4594 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004597 }
4598
Willy Tarreaub80c2302007-11-30 20:51:32 +01004599 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004600 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004601
4602 if (strcmp(args[1], "fail") == 0) {
4603 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004604 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004605 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4606 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004609 }
4610
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004611 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4612 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4613 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004616 }
4617 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4618 }
4619 else {
4620 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004623 }
4624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625#ifdef TPROXY
4626 else if (!strcmp(args[0], "transparent")) {
4627 /* enable transparent proxy connections */
4628 curproxy->options |= PR_O_TRANSP;
4629 }
4630#endif
4631 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004632 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004634
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 if (*(args[1]) == 0) {
4636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 }
4640 curproxy->maxconn = atol(args[1]);
4641 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004642 else if (!strcmp(args[0], "backlog")) { /* backlog */
4643 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004644 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004645
4646 if (*(args[1]) == 0) {
4647 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004650 }
4651 curproxy->backlog = atol(args[1]);
4652 }
Willy Tarreau86034312006-12-29 00:10:33 +01004653 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004656
Willy Tarreau86034312006-12-29 00:10:33 +01004657 if (*(args[1]) == 0) {
4658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004661 }
4662 curproxy->fullconn = atol(args[1]);
4663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4665 if (*(args[1]) == 0) {
4666 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004670 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4671 if (err) {
4672 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4673 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004676 }
4677 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 }
4679 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004680 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004681 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004682 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004683
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 if (curproxy == &defproxy) {
4685 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004689 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004690 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004691
Willy Tarreau902636f2013-03-10 19:44:48 +01004692 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004693 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004694 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004695 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004696 goto out;
4697 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004698
4699 proto = protocol_by_family(sk->ss_family);
4700 if (!proto || !proto->connect) {
4701 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4702 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004703 err_code |= ERR_ALERT | ERR_FATAL;
4704 goto out;
4705 }
4706
4707 if (port1 != port2) {
4708 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4709 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004713
4714 if (!port1) {
4715 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4716 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
4719 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004720
Willy Tarreaud5191e72010-02-09 20:50:45 +01004721 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004722 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 }
4724 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004727
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004728 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4729 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004734 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004735 /**
4736 * The syntax for hash-type config element is
4737 * hash-type {map-based|consistent} [[<algo>] avalanche]
4738 *
4739 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4740 */
4741 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004742
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4744 err_code |= ERR_WARN;
4745
4746 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004747 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4748 }
4749 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004750 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4751 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004752 else if (strcmp(args[1], "avalanche") == 0) {
4753 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]);
4754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004756 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004757 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004758 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761 }
Bhaskar98634f02013-10-29 23:30:51 -04004762
4763 /* set the hash function to use */
4764 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004765 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004766 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004767
4768 /* if consistent with no argument, then avalanche modifier is also applied */
4769 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4770 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004771 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004772 /* set the hash function */
4773 if (!strcmp(args[2], "sdbm")) {
4774 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4775 }
4776 else if (!strcmp(args[2], "djb2")) {
4777 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004778 } else if (!strcmp(args[2], "wt6")) {
4779 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004780 }
4781 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004782 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 -05004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
4785 }
4786
4787 /* set the hash modifier */
4788 if (!strcmp(args[3], "avalanche")) {
4789 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4790 }
4791 else if (*args[3]) {
4792 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4793 err_code |= ERR_ALERT | ERR_FATAL;
4794 goto out;
4795 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004796 }
William Lallemanda73203e2012-03-12 12:48:57 +01004797 }
William Lallemanda73203e2012-03-12 12:48:57 +01004798 else if (strcmp(args[0], "unique-id-format") == 0) {
4799 if (!*(args[1])) {
4800 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
William Lallemand3203ff42012-11-11 17:30:56 +01004804 if (*(args[2])) {
4805 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
4808 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004809 free(curproxy->conf.uniqueid_format_string);
4810 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004811
Willy Tarreau62a61232013-04-12 18:13:46 +02004812 free(curproxy->conf.uif_file);
4813 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4814 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004815 }
William Lallemanda73203e2012-03-12 12:48:57 +01004816
4817 else if (strcmp(args[0], "unique-id-header") == 0) {
4818 if (!*(args[1])) {
4819 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
4822 }
4823 free(curproxy->header_unique_id);
4824 curproxy->header_unique_id = strdup(args[1]);
4825 }
4826
William Lallemand723b73a2012-02-08 16:37:49 +01004827 else if (strcmp(args[0], "log-format") == 0) {
4828 if (!*(args[1])) {
4829 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
4832 }
William Lallemand3203ff42012-11-11 17:30:56 +01004833 if (*(args[2])) {
4834 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004838
Willy Tarreau62a61232013-04-12 18:13:46 +02004839 if (curproxy->conf.logformat_string != default_http_log_format &&
4840 curproxy->conf.logformat_string != default_tcp_log_format &&
4841 curproxy->conf.logformat_string != clf_http_log_format)
4842 free(curproxy->conf.logformat_string);
4843 curproxy->conf.logformat_string = strdup(args[1]);
4844
4845 free(curproxy->conf.lfs_file);
4846 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4847 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004848
4849 /* get a chance to improve log-format error reporting by
4850 * reporting the correct line-number when possible.
4851 */
4852 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4853 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4854 file, linenum, curproxy->id);
4855 err_code |= ERR_WARN;
4856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 }
William Lallemand723b73a2012-02-08 16:37:49 +01004858
William Lallemand0f99e342011-10-12 17:50:54 +02004859 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4860 /* delete previous herited or defined syslog servers */
4861 struct logsrv *back;
4862
4863 if (*(args[1]) != 0) {
4864 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
4868
William Lallemand723b73a2012-02-08 16:37:49 +01004869 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4870 LIST_DEL(&tmplogsrv->list);
4871 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004872 }
4873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004875 struct logsrv *logsrv;
4876
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004878 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004879 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004880 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004881 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004882 LIST_INIT(&node->list);
4883 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 }
4886 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004887 struct sockaddr_storage *sk;
4888 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004889 int arg = 0;
4890 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004891
4892 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004894 /* just after the address, a length may be specified */
4895 if (strcmp(args[arg+2], "len") == 0) {
4896 len = atoi(args[arg+3]);
4897 if (len < 80 || len > 65535) {
4898 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4899 file, linenum, args[arg+3]);
4900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902 }
4903 logsrv->maxlen = len;
4904
4905 /* skip these two args */
4906 arg += 2;
4907 }
4908 else
4909 logsrv->maxlen = MAX_SYSLOG_LEN;
4910
4911 if (logsrv->maxlen > global.max_syslog_len) {
4912 global.max_syslog_len = logsrv->maxlen;
4913 logline = realloc(logline, global.max_syslog_len + 1);
4914 }
4915
4916 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004917 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004918 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
4921
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 }
4923
William Lallemand0f99e342011-10-12 17:50:54 +02004924 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004925 if (*(args[arg+3])) {
4926 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004927 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004928 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
4931
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
4933 }
4934
William Lallemand0f99e342011-10-12 17:50:54 +02004935 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004936 if (*(args[arg+4])) {
4937 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004938 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004939 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004943 }
4944 }
4945
Willy Tarreau902636f2013-03-10 19:44:48 +01004946 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004947 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004948 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004949 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004950 goto out;
4951 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004952
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004953 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004954
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004955 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004956 if (port1 != port2) {
4957 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4958 file, linenum, args[0], args[1]);
4959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
4961 }
4962
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004963 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004964 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
William Lallemand0f99e342011-10-12 17:50:54 +02004966
4967 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 }
4969 else {
4970 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4971 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 }
4976 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004977 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004978 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004979 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004980 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004981
Willy Tarreau977b8e42006-12-29 14:19:17 +01004982 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004984
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004986 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4987 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004991
4992 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004993 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4994 free(curproxy->conn_src.iface_name);
4995 curproxy->conn_src.iface_name = NULL;
4996 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004997
Willy Tarreau902636f2013-03-10 19:44:48 +01004998 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004999 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005000 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005001 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005002 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005003 goto out;
5004 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005005
5006 proto = protocol_by_family(sk->ss_family);
5007 if (!proto || !proto->connect) {
5008 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005009 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
5012 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005013
5014 if (port1 != port2) {
5015 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5016 file, linenum, args[0], args[1]);
5017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019 }
5020
Willy Tarreauef9a3602012-12-08 22:29:20 +01005021 curproxy->conn_src.source_addr = *sk;
5022 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005023
5024 cur_arg = 2;
5025 while (*(args[cur_arg])) {
5026 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005027#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5028#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005029 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005030 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5031 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005034 }
5035#endif
5036 if (!*args[cur_arg + 1]) {
5037 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5038 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005041 }
5042
5043 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005044 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5045 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005046 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005047 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5048 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005049 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5050 char *name, *end;
5051
5052 name = args[cur_arg+1] + 7;
5053 while (isspace(*name))
5054 name++;
5055
5056 end = name;
5057 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5058 end++;
5059
Willy Tarreauef9a3602012-12-08 22:29:20 +01005060 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5061 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5062 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5063 curproxy->conn_src.bind_hdr_len = end - name;
5064 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5065 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5066 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005067
5068 /* now look for an occurrence number */
5069 while (isspace(*end))
5070 end++;
5071 if (*end == ',') {
5072 end++;
5073 name = end;
5074 if (*end == '-')
5075 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005076 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005077 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005078 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005079 }
5080
Willy Tarreauef9a3602012-12-08 22:29:20 +01005081 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005082 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5083 " occurrences values smaller than %d.\n",
5084 file, linenum, MAX_HDR_HISTORY);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005088 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005089 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005090
Willy Tarreau902636f2013-03-10 19:44:48 +01005091 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005092 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005093 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005094 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005095 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005096 goto out;
5097 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005098
5099 proto = protocol_by_family(sk->ss_family);
5100 if (!proto || !proto->connect) {
5101 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5102 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
5105 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005106
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005107 if (port1 != port2) {
5108 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5109 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
5112 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005113 curproxy->conn_src.tproxy_addr = *sk;
5114 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005115 }
5116 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005117#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005119#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005120#else /* no TPROXY support */
5121 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005122 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005125#endif
5126 cur_arg += 2;
5127 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005128 }
5129
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005130 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5131#ifdef SO_BINDTODEVICE
5132 if (!*args[cur_arg + 1]) {
5133 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5134 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005137 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005138 free(curproxy->conn_src.iface_name);
5139 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5140 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005141 global.last_checks |= LSTCHK_NETADM;
5142#else
5143 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5144 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005147#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005148 cur_arg += 2;
5149 continue;
5150 }
5151 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005152 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005157 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5158 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5159 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5166 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170
5171 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005172 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005173 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005174 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
5177 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005179 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005180 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005181 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
5184 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005186 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005187 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 }
5191 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005193 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005194 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
5198 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005200 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005201 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005205 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005207 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005208 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005209 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005210 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005211 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005212 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005214 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005215 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005217 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005218
5219 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5220 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 +01005221 }
5222 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005223 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005224 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005225 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005226 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005227 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005228
5229 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5230 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 +01005231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005233 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5235 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239
5240 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005241 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005242 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005245 }
5246 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005247 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005248 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005249 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005250 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005252 }
5253 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005255 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005256 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005257 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 }
5260 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005262 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005263 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
5267 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005269 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005270 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005271 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005274 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005276 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005277 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005279 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005282 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005283
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 if (curproxy == &defproxy) {
5285 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005289 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005290 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 if (*(args[1]) == 0) {
5293 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005297
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005298 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005299 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5300 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5301 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005305 err_code |= warnif_cond_conflicts(cond,
5306 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5307 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005308 }
5309 else if (*args[2]) {
5310 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5311 file, linenum, args[0], args[2]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005316 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005317 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005318 wl->s = strdup(args[1]);
5319 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005320 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 }
5322 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005323 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005329
Willy Tarreauade5ec42010-01-28 19:33:49 +01005330 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005331 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005332 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005333 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 }
5336 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005337 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005338 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005339 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005340 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 }
5343 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005344 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005345 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005346 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005347 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 }
5350 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005351 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
5357
Willy Tarreauade5ec42010-01-28 19:33:49 +01005358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005359 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005360 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
5364 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005366 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 }
5371 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005373 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
5378 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005379 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005380
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 if (curproxy == &defproxy) {
5382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005386 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 if (*(args[1]) == 0) {
5390 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
5394
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005395 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005396 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5397 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5398 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005402 err_code |= warnif_cond_conflicts(cond,
5403 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5404 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005405 }
5406 else if (*args[2]) {
5407 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5408 file, linenum, args[0], args[2]);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005413 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005414 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005415 wl->s = strdup(args[1]);
5416 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417 }
5418 else if (!strcmp(args[0], "errorloc") ||
5419 !strcmp(args[0], "errorloc302") ||
5420 !strcmp(args[0], "errorloc303")) { /* error location */
5421 int errnum, errlen;
5422 char *err;
5423
Willy Tarreau977b8e42006-12-29 14:19:17 +01005424 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005426
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005428 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 }
5432
5433 errnum = atol(args[1]);
5434 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005435 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5436 err = malloc(errlen);
5437 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005439 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5440 err = malloc(errlen);
5441 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 }
5443
Willy Tarreau0f772532006-12-23 20:51:41 +01005444 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5445 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005446 chunk_destroy(&curproxy->errmsg[rc]);
5447 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005448 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005451
5452 if (rc >= HTTP_ERR_SIZE) {
5453 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5454 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 free(err);
5456 }
5457 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005458 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5459 int errnum, errlen, fd;
5460 char *err;
5461 struct stat stat;
5462
5463 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005464 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005465
5466 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005467 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005470 }
5471
5472 fd = open(args[2], O_RDONLY);
5473 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5474 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5475 file, linenum, args[2], args[1]);
5476 if (fd >= 0)
5477 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005480 }
5481
Willy Tarreau27a674e2009-08-17 07:23:33 +02005482 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005483 errlen = stat.st_size;
5484 } else {
5485 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005486 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005487 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005488 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005489 }
5490
5491 err = malloc(errlen); /* malloc() must succeed during parsing */
5492 errnum = read(fd, err, errlen);
5493 if (errnum != errlen) {
5494 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5495 file, linenum, args[2], args[1]);
5496 close(fd);
5497 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500 }
5501 close(fd);
5502
5503 errnum = atol(args[1]);
5504 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5505 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005506 chunk_destroy(&curproxy->errmsg[rc]);
5507 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005508 break;
5509 }
5510 }
5511
5512 if (rc >= HTTP_ERR_SIZE) {
5513 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5514 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005515 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005516 free(err);
5517 }
5518 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005519 else if (!strcmp(args[0], "compression")) {
5520 struct comp *comp;
5521 if (curproxy->comp == NULL) {
5522 comp = calloc(1, sizeof(struct comp));
5523 curproxy->comp = comp;
5524 } else {
5525 comp = curproxy->comp;
5526 }
5527
5528 if (!strcmp(args[1], "algo")) {
5529 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005530 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005531
William Lallemand82fe75c2012-10-23 10:25:10 +02005532 cur_arg = 2;
5533 if (!*args[cur_arg]) {
5534 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5535 file, linenum, args[0]);
5536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
5538 }
5539 while (*(args[cur_arg])) {
5540 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5541 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5542 file, linenum, args[0], args[cur_arg]);
5543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
5545 }
William Lallemand552df672012-11-07 13:21:47 +01005546 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5547 curproxy->comp->algos->end(&ctx);
5548 } else {
5549 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5550 file, linenum, args[0], args[cur_arg]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005554 cur_arg ++;
5555 continue;
5556 }
5557 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005558 else if (!strcmp(args[1], "offload")) {
5559 comp->offload = 1;
5560 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005561 else if (!strcmp(args[1], "type")) {
5562 int cur_arg;
5563 cur_arg = 2;
5564 if (!*args[cur_arg]) {
5565 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5566 file, linenum, args[0]);
5567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
5569 }
5570 while (*(args[cur_arg])) {
5571 comp_append_type(comp, args[cur_arg]);
5572 cur_arg ++;
5573 continue;
5574 }
5575 }
5576 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005577 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005578 file, linenum, args[0]);
5579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
5581 }
5582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005584 struct cfg_kw_list *kwl;
5585 int index;
5586
5587 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5588 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5589 if (kwl->kw[index].section != CFG_LISTEN)
5590 continue;
5591 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5592 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005593 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005594 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005595 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005598 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005599 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005600 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_WARN;
5602 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005603 }
Willy Tarreau93893792009-07-23 13:19:11 +02005604 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005605 }
5606 }
5607 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005608
Willy Tarreau6daf3432008-01-22 16:44:08 +01005609 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
Willy Tarreau93893792009-07-23 13:19:11 +02005613 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005614 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005615 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616}
5617
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005618int
5619cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5620{
5621
5622 int err_code = 0;
5623 const char *err;
5624
5625 if (!strcmp(args[0], "userlist")) { /* new userlist */
5626 struct userlist *newul;
5627
5628 if (!*args[1]) {
5629 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5630 file, linenum, args[0]);
5631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
5633 }
5634
5635 err = invalid_char(args[1]);
5636 if (err) {
5637 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5638 file, linenum, *err, args[0], args[1]);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
5642
5643 for (newul = userlist; newul; newul = newul->next)
5644 if (!strcmp(newul->name, args[1])) {
5645 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5646 file, linenum, args[1]);
5647 err_code |= ERR_WARN;
5648 goto out;
5649 }
5650
5651 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5652 if (!newul) {
5653 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5654 err_code |= ERR_ALERT | ERR_ABORT;
5655 goto out;
5656 }
5657
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005658 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005659 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005660 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5661 err_code |= ERR_ALERT | ERR_ABORT;
5662 goto out;
5663 }
5664
5665 newul->next = userlist;
5666 userlist = newul;
5667
5668 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005669 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005670 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005671 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005672
5673 if (!*args[1]) {
5674 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5675 file, linenum, args[0]);
5676 err_code |= ERR_ALERT | ERR_FATAL;
5677 goto out;
5678 }
5679
5680 err = invalid_char(args[1]);
5681 if (err) {
5682 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5683 file, linenum, *err, args[0], args[1]);
5684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
5687
William Lallemandfaf33152015-05-28 18:03:51 +02005688 if (!userlist)
5689 goto out;
5690
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005691 for (ag = userlist->groups; ag; ag = ag->next)
5692 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005693 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5694 file, linenum, args[1], userlist->name);
5695 err_code |= ERR_ALERT;
5696 goto out;
5697 }
5698
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005699 ag = calloc(1, sizeof(*ag));
5700 if (!ag) {
5701 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5702 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005703 goto out;
5704 }
5705
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005706 ag->name = strdup(args[1]);
5707 if (!ag) {
5708 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5709 err_code |= ERR_ALERT | ERR_ABORT;
5710 goto out;
5711 }
5712
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005713 cur_arg = 2;
5714
5715 while (*args[cur_arg]) {
5716 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005717 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005718 cur_arg += 2;
5719 continue;
5720 } else {
5721 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5722 file, linenum, args[0]);
5723 err_code |= ERR_ALERT | ERR_FATAL;
5724 goto out;
5725 }
5726 }
5727
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005728 ag->next = userlist->groups;
5729 userlist->groups = ag;
5730
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005731 } else if (!strcmp(args[0], "user")) { /* new user */
5732 struct auth_users *newuser;
5733 int cur_arg;
5734
5735 if (!*args[1]) {
5736 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5737 file, linenum, args[0]);
5738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
5740 }
William Lallemandfaf33152015-05-28 18:03:51 +02005741 if (!userlist)
5742 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005743
5744 for (newuser = userlist->users; newuser; newuser = newuser->next)
5745 if (!strcmp(newuser->user, args[1])) {
5746 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5747 file, linenum, args[1], userlist->name);
5748 err_code |= ERR_ALERT;
5749 goto out;
5750 }
5751
5752 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5753 if (!newuser) {
5754 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5755 err_code |= ERR_ALERT | ERR_ABORT;
5756 goto out;
5757 }
5758
5759 newuser->user = strdup(args[1]);
5760
5761 newuser->next = userlist->users;
5762 userlist->users = newuser;
5763
5764 cur_arg = 2;
5765
5766 while (*args[cur_arg]) {
5767 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005768#ifdef CONFIG_HAP_CRYPT
5769 if (!crypt("", args[cur_arg + 1])) {
5770 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5771 file, linenum, newuser->user);
5772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
5774 }
5775#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005776 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5777 file, linenum);
5778 err_code |= ERR_ALERT;
5779#endif
5780 newuser->pass = strdup(args[cur_arg + 1]);
5781 cur_arg += 2;
5782 continue;
5783 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5784 newuser->pass = strdup(args[cur_arg + 1]);
5785 newuser->flags |= AU_O_INSECURE;
5786 cur_arg += 2;
5787 continue;
5788 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005789 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005790 cur_arg += 2;
5791 continue;
5792 } else {
5793 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5794 file, linenum, args[0]);
5795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
5797 }
5798 }
5799 } else {
5800 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5801 err_code |= ERR_ALERT | ERR_FATAL;
5802 }
5803
5804out:
5805 return err_code;
5806}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807
5808/*
5809 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005810 * Returns the error code, 0 if OK, or any combination of :
5811 * - ERR_ABORT: must abort ASAP
5812 * - ERR_FATAL: we can continue parsing but not start the service
5813 * - ERR_WARN: a warning has been emitted
5814 * - ERR_ALERT: an alert has been emitted
5815 * Only the two first ones can stop processing, the two others are just
5816 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005818int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005820 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 FILE *f;
5822 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005823 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005824 struct cfg_section *cs = NULL;
5825 struct cfg_section *ics;
5826
5827 /* Register internal sections */
5828 if (!cfg_register_section("listen", cfg_parse_listen) ||
5829 !cfg_register_section("frontend", cfg_parse_listen) ||
5830 !cfg_register_section("backend", cfg_parse_listen) ||
5831 !cfg_register_section("ruleset", cfg_parse_listen) ||
5832 !cfg_register_section("defaults", cfg_parse_listen) ||
5833 !cfg_register_section("global", cfg_parse_global) ||
5834 !cfg_register_section("userlist", cfg_parse_users) ||
5835 !cfg_register_section("peers", cfg_parse_peers))
5836 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 if ((f=fopen(file,"r")) == NULL)
5839 return -1;
5840
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005841 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005842 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005843 char *end;
5844 char *args[MAX_LINE_ARGS + 1];
5845 char *line = thisline;
5846
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 linenum++;
5848
5849 end = line + strlen(line);
5850
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005851 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5852 /* Check if we reached the limit and the last char is not \n.
5853 * Watch out for the last line without the terminating '\n'!
5854 */
5855 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005856 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005857 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005858 }
5859
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005861 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 line++;
5863
5864 arg = 0;
5865 args[arg] = line;
5866
5867 while (*line && arg < MAX_LINE_ARGS) {
5868 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5869 * C equivalent value. Other combinations left unchanged (eg: \1).
5870 */
5871 if (*line == '\\') {
5872 int skip = 0;
5873 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5874 *line = line[1];
5875 skip = 1;
5876 }
5877 else if (line[1] == 'r') {
5878 *line = '\r';
5879 skip = 1;
5880 }
5881 else if (line[1] == 'n') {
5882 *line = '\n';
5883 skip = 1;
5884 }
5885 else if (line[1] == 't') {
5886 *line = '\t';
5887 skip = 1;
5888 }
5889 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005890 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 unsigned char hex1, hex2;
5892 hex1 = toupper(line[2]) - '0';
5893 hex2 = toupper(line[3]) - '0';
5894 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5895 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5896 *line = (hex1<<4) + hex2;
5897 skip = 3;
5898 }
5899 else {
5900 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005901 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 }
5903 }
5904 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005905 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 end -= skip;
5907 }
5908 line++;
5909 }
5910 else if (*line == '#' || *line == '\n' || *line == '\r') {
5911 /* end of string, end of loop */
5912 *line = 0;
5913 break;
5914 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005915 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005917 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005918 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 line++;
5920 args[++arg] = line;
5921 }
5922 else {
5923 line++;
5924 }
5925 }
5926
5927 /* empty line */
5928 if (!**args)
5929 continue;
5930
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005931 if (*line) {
5932 /* we had to stop due to too many args.
5933 * Let's terminate the string, print the offending part then cut the
5934 * last arg.
5935 */
5936 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5937 line++;
5938 *line = '\0';
5939
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005940 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005941 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005942 err_code |= ERR_ALERT | ERR_FATAL;
5943 args[arg] = line;
5944 }
5945
Willy Tarreau540abe42007-05-02 20:50:16 +02005946 /* zero out remaining args and ensure that at least one entry
5947 * is zeroed out.
5948 */
5949 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950 args[arg] = line;
5951 }
5952
Willy Tarreau3842f002009-06-14 11:39:52 +02005953 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005954 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005955 char *tmp;
5956
Willy Tarreau3842f002009-06-14 11:39:52 +02005957 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005958 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005959 for (arg=0; *args[arg+1]; arg++)
5960 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005961 *tmp = '\0'; // fix the next arg to \0
5962 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005963 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005964 else if (!strcmp(args[0], "default")) {
5965 kwm = KWM_DEF;
5966 for (arg=0; *args[arg+1]; arg++)
5967 args[arg] = args[arg+1]; // shift args after inversion
5968 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005969
William Lallemand0f99e342011-10-12 17:50:54 +02005970 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5971 strcmp(args[0], "log") != 0) {
5972 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005973 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005974 }
5975
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005976 /* detect section start */
5977 list_for_each_entry(ics, &sections, list) {
5978 if (strcmp(args[0], ics->section_name) == 0) {
5979 cursection = ics->section_name;
5980 cs = ics;
5981 break;
5982 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005983 }
5984
Willy Tarreaubaaee002006-06-26 02:48:02 +02005985 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005986 if (cs)
5987 err_code |= cs->section_parser(file, linenum, args, kwm);
5988 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005989 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005990 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005992
5993 if (err_code & ERR_ABORT)
5994 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005996 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005998 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005999}
6000
Willy Tarreau5436afc2014-09-16 12:17:36 +02006001/* This function propagates processes from frontend <from> to backend <to> so
6002 * that it is always guaranteed that a backend pointed to by a frontend is
6003 * bound to all of its processes. After that, if the target is a "listen"
6004 * instance, the function recursively descends the target's own targets along
6005 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6006 * checked first to ensure that <to> is already bound to all processes of
6007 * <from>, there is no risk of looping and we ensure to follow the shortest
6008 * path to the destination.
6009 *
6010 * It is possible to set <to> to NULL for the first call so that the function
6011 * takes care of visiting the initial frontend in <from>.
6012 *
6013 * It is important to note that the function relies on the fact that all names
6014 * have already been resolved.
6015 */
6016void propagate_processes(struct proxy *from, struct proxy *to)
6017{
6018 struct switching_rule *rule;
6019 struct hdr_exp *exp;
6020
6021 if (to) {
6022 /* check whether we need to go down */
6023 if (from->bind_proc &&
6024 (from->bind_proc & to->bind_proc) == from->bind_proc)
6025 return;
6026
6027 if (!from->bind_proc && !to->bind_proc)
6028 return;
6029
6030 to->bind_proc = from->bind_proc ?
6031 (to->bind_proc | from->bind_proc) : 0;
6032
6033 /* now propagate down */
6034 from = to;
6035 }
6036
Willy Tarreau7110f382014-12-18 13:56:26 +01006037 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006038 return;
6039
Willy Tarreaued061c02014-12-18 14:00:43 +01006040 if (from->state == PR_STSTOPPED)
6041 return;
6042
Willy Tarreau5436afc2014-09-16 12:17:36 +02006043 /* default_backend */
6044 if (from->defbe.be)
6045 propagate_processes(from, from->defbe.be);
6046
6047 /* use_backend */
6048 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006049 if (rule->dynamic)
6050 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006051 to = rule->be.backend;
6052 propagate_processes(from, to);
6053 }
6054
6055 /* reqsetbe */
6056 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6057 if (exp->action != ACT_SETBE)
6058 continue;
6059 to = (struct proxy *)exp->replace;
6060 propagate_processes(from, to);
6061 }
6062}
6063
Willy Tarreaubb925012009-07-23 13:36:36 +02006064/*
6065 * Returns the error code, 0 if OK, or any combination of :
6066 * - ERR_ABORT: must abort ASAP
6067 * - ERR_FATAL: we can continue parsing but not start the service
6068 * - ERR_WARN: a warning has been emitted
6069 * - ERR_ALERT: an alert has been emitted
6070 * Only the two first ones can stop processing, the two others are just
6071 * indicators.
6072 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006073int check_config_validity()
6074{
6075 int cfgerr = 0;
6076 struct proxy *curproxy = NULL;
6077 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006078 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006079 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006080 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006082 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006083 /*
6084 * Now, check for the integrity of all that we have collected.
6085 */
6086
6087 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006088 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089
Willy Tarreau193b8c62012-11-22 00:17:38 +01006090 if (!global.tune.max_http_hdr)
6091 global.tune.max_http_hdr = MAX_HTTP_HDR;
6092
6093 if (!global.tune.cookie_len)
6094 global.tune.cookie_len = CAPTURE_LEN;
6095
6096 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6097
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006098 /* Post initialisation of the users and groups lists. */
6099 err_code = userlist_postinit();
6100 if (err_code != ERR_NONE)
6101 goto out;
6102
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006103 /* first, we will invert the proxy list order */
6104 curproxy = NULL;
6105 while (proxy) {
6106 struct proxy *next;
6107
6108 next = proxy->next;
6109 proxy->next = curproxy;
6110 curproxy = proxy;
6111 if (!next)
6112 break;
6113 proxy = next;
6114 }
6115
Willy Tarreau91b00c22014-09-16 13:41:21 +02006116 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006117 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006118 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006119 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006120 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006121 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006122 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006123
Willy Tarreau050536d2012-10-04 08:47:34 +02006124 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006125 /* proxy ID not set, use automatic numbering with first
6126 * spare entry starting with next_pxid.
6127 */
6128 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6129 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6130 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006131 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006132 next_pxid++;
6133
Willy Tarreau55ea7572007-06-17 19:56:27 +02006134
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006136 /* ensure we don't keep listeners uselessly bound */
6137 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006138 free((void *)curproxy->table.peers.name);
6139 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 continue;
6141 }
6142
Willy Tarreau102df612014-05-07 23:56:38 +02006143 /* Check multi-process mode compatibility for the current proxy */
6144
6145 if (curproxy->bind_proc) {
6146 /* an explicit bind-process was specified, let's check how many
6147 * processes remain.
6148 */
David Carlier6de4c2f2015-07-02 07:00:17 +00006149 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02006150
6151 curproxy->bind_proc &= nbits(global.nbproc);
6152 if (!curproxy->bind_proc && nbproc == 1) {
6153 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);
6154 curproxy->bind_proc = 1;
6155 }
6156 else if (!curproxy->bind_proc && nbproc > 1) {
6157 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);
6158 curproxy->bind_proc = 0;
6159 }
6160 }
6161
Willy Tarreau3d209582014-05-09 17:06:11 +02006162 /* check and reduce the bind-proc of each listener */
6163 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6164 unsigned long mask;
6165
6166 if (!bind_conf->bind_proc)
6167 continue;
6168
6169 mask = nbits(global.nbproc);
6170 if (curproxy->bind_proc)
6171 mask &= curproxy->bind_proc;
6172 /* mask cannot be null here thanks to the previous checks */
6173
David Carlier6de4c2f2015-07-02 07:00:17 +00006174 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02006175 bind_conf->bind_proc &= mask;
6176
6177 if (!bind_conf->bind_proc && nbproc == 1) {
6178 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",
6179 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6180 bind_conf->bind_proc = mask & ~(mask - 1);
6181 }
6182 else if (!bind_conf->bind_proc && nbproc > 1) {
6183 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",
6184 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6185 bind_conf->bind_proc = 0;
6186 }
6187 }
6188
Willy Tarreauff01a212009-03-15 13:46:16 +01006189 switch (curproxy->mode) {
6190 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006191 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006192 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006193 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6194 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006195 cfgerr++;
6196 }
6197
6198 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006199 Warning("config : servers will be ignored for %s '%s'.\n",
6200 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006201 break;
6202
6203 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006204 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006205 break;
6206
6207 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006208 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006209 break;
6210 }
6211
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006212 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006213 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006214 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006215 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6216 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006217 cfgerr++;
6218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006220 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006221 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6222 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006223 cfgerr++;
6224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006226 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006227 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6228 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006229 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006230 }
6231 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006232 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006233 /* If no LB algo is set in a backend, and we're not in
6234 * transparent mode, dispatch mode nor proxy mode, we
6235 * want to use balance roundrobin by default.
6236 */
6237 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6238 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239 }
6240 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006241
Willy Tarreau1620ec32011-08-06 17:05:02 +02006242 if (curproxy->options & PR_O_DISPATCH)
6243 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6244 else if (curproxy->options & PR_O_HTTP_PROXY)
6245 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6246 else if (curproxy->options & PR_O_TRANSP)
6247 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006248
Willy Tarreau1620ec32011-08-06 17:05:02 +02006249 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6250 if (curproxy->options & PR_O_DISABLE404) {
6251 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6252 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6253 err_code |= ERR_WARN;
6254 curproxy->options &= ~PR_O_DISABLE404;
6255 }
6256 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6257 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6258 "send-state", proxy_type_str(curproxy), curproxy->id);
6259 err_code |= ERR_WARN;
6260 curproxy->options &= ~PR_O2_CHK_SNDST;
6261 }
Willy Tarreauef781042010-01-27 11:53:01 +01006262 }
6263
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006264 /* if a default backend was specified, let's find it */
6265 if (curproxy->defbe.name) {
6266 struct proxy *target;
6267
Alex Williams96532db2009-11-01 21:27:13 -05006268 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006269 if (!target) {
6270 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6271 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006272 cfgerr++;
6273 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006274 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6275 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006276 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006277 } else {
6278 free(curproxy->defbe.name);
6279 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006280
6281 /* Emit a warning if this proxy also has some servers */
6282 if (curproxy->srv) {
6283 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6284 curproxy->id);
6285 err_code |= ERR_WARN;
6286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 }
6288 }
6289
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006290 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006291 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6292 /* map jump target for ACT_SETBE in req_rep chain */
6293 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006294 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006295 struct proxy *target;
6296
Willy Tarreaua496b602006-12-17 23:15:24 +01006297 if (exp->action != ACT_SETBE)
6298 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006299
Alex Williams96532db2009-11-01 21:27:13 -05006300 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006301 if (!target) {
6302 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6303 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006304 cfgerr++;
6305 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006306 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6307 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006308 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006309 } else {
6310 free((void *)exp->replace);
6311 exp->replace = (const char *)target;
6312 }
6313 }
6314 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006315
6316 /* find the target proxy for 'use_backend' rules */
6317 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006318 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006319 struct logformat_node *node;
6320 char *pxname;
6321
6322 /* Try to parse the string as a log format expression. If the result
6323 * of the parsing is only one entry containing a simple string, then
6324 * it's a standard string corresponding to a static rule, thus the
6325 * parsing is cancelled and be.name is restored to be resolved.
6326 */
6327 pxname = rule->be.name;
6328 LIST_INIT(&rule->be.expr);
6329 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6330 curproxy->conf.args.file, curproxy->conf.args.line);
6331 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6332
6333 if (!LIST_ISEMPTY(&rule->be.expr)) {
6334 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6335 rule->dynamic = 1;
6336 free(pxname);
6337 continue;
6338 }
6339 /* simple string: free the expression and fall back to static rule */
6340 free(node->arg);
6341 free(node);
6342 }
6343
6344 rule->dynamic = 0;
6345 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006346
Alex Williams96532db2009-11-01 21:27:13 -05006347 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006348
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006349 if (!target) {
6350 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6351 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006352 cfgerr++;
6353 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006354 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6355 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006356 cfgerr++;
6357 } else {
6358 free((void *)rule->be.name);
6359 rule->be.backend = target;
6360 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006361 }
6362
Willy Tarreau5436afc2014-09-16 12:17:36 +02006363 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006364 list_for_each_entry(srule, &curproxy->server_rules, list) {
6365 struct server *target = findserver(curproxy, srule->srv.name);
6366
6367 if (!target) {
6368 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6369 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6370 cfgerr++;
6371 continue;
6372 }
6373 free((void *)srule->srv.name);
6374 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006375 }
6376
Emeric Brunb982a3d2010-01-04 15:45:53 +01006377 /* find the target table for 'stick' rules */
6378 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6379 struct proxy *target;
6380
Emeric Brun1d33b292010-01-04 15:47:17 +01006381 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6382 if (mrule->flags & STK_IS_STORE)
6383 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6384
Emeric Brunb982a3d2010-01-04 15:45:53 +01006385 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006386 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006387 else
6388 target = curproxy;
6389
6390 if (!target) {
6391 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6392 curproxy->id, mrule->table.name);
6393 cfgerr++;
6394 }
6395 else if (target->table.size == 0) {
6396 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6397 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6398 cfgerr++;
6399 }
Willy Tarreau12785782012-04-27 21:37:17 +02006400 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6401 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006402 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6403 cfgerr++;
6404 }
6405 else {
6406 free((void *)mrule->table.name);
6407 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006408 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006409 }
6410 }
6411
6412 /* find the target table for 'store response' rules */
6413 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6414 struct proxy *target;
6415
Emeric Brun1d33b292010-01-04 15:47:17 +01006416 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6417
Emeric Brunb982a3d2010-01-04 15:45:53 +01006418 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006419 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006420 else
6421 target = curproxy;
6422
6423 if (!target) {
6424 Alert("Proxy '%s': unable to find store table '%s'.\n",
6425 curproxy->id, mrule->table.name);
6426 cfgerr++;
6427 }
6428 else if (target->table.size == 0) {
6429 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6430 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6431 cfgerr++;
6432 }
Willy Tarreau12785782012-04-27 21:37:17 +02006433 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6434 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006435 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6436 cfgerr++;
6437 }
6438 else {
6439 free((void *)mrule->table.name);
6440 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006441 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006442 }
6443 }
6444
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006445 /* find the target table for 'tcp-request' layer 4 rules */
6446 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6447 struct proxy *target;
6448
Willy Tarreaub4c84932013-07-23 19:15:30 +02006449 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006450 continue;
6451
6452 if (trule->act_prm.trk_ctr.table.n)
6453 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6454 else
6455 target = curproxy;
6456
6457 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006458 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6459 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006460 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006461 cfgerr++;
6462 }
6463 else if (target->table.size == 0) {
6464 Alert("Proxy '%s': table '%s' used but not configured.\n",
6465 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6466 cfgerr++;
6467 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006468 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6469 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6470 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 +01006471 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006472 cfgerr++;
6473 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006474 else {
6475 free(trule->act_prm.trk_ctr.table.n);
6476 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006477 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006478 * to pass a list of counters to track and allocate them right here using
6479 * stktable_alloc_data_type().
6480 */
6481 }
6482 }
6483
Willy Tarreaud1f96522010-08-03 19:34:32 +02006484 /* find the target table for 'tcp-request' layer 6 rules */
6485 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6486 struct proxy *target;
6487
Willy Tarreaub4c84932013-07-23 19:15:30 +02006488 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006489 continue;
6490
6491 if (trule->act_prm.trk_ctr.table.n)
6492 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6493 else
6494 target = curproxy;
6495
6496 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006497 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6498 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006499 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006500 cfgerr++;
6501 }
6502 else if (target->table.size == 0) {
6503 Alert("Proxy '%s': table '%s' used but not configured.\n",
6504 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6505 cfgerr++;
6506 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006507 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6508 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6509 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 +01006510 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006511 cfgerr++;
6512 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006513 else {
6514 free(trule->act_prm.trk_ctr.table.n);
6515 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006516 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006517 * to pass a list of counters to track and allocate them right here using
6518 * stktable_alloc_data_type().
6519 */
6520 }
6521 }
6522
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006523 /* move any "block" rules at the beginning of the http-request rules */
6524 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6525 /* insert block_rules into http_req_rules at the beginning */
6526 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6527 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6528 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6529 curproxy->http_req_rules.n = curproxy->block_rules.n;
6530 LIST_INIT(&curproxy->block_rules);
6531 }
6532
Emeric Brun32da3c42010-09-23 18:39:19 +02006533 if (curproxy->table.peers.name) {
6534 struct peers *curpeers = peers;
6535
6536 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6537 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6538 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006539 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006540 break;
6541 }
6542 }
6543
6544 if (!curpeers) {
6545 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6546 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006547 free((void *)curproxy->table.peers.name);
6548 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006549 cfgerr++;
6550 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006551 else if (curpeers->state == PR_STSTOPPED) {
6552 /* silently disable this peers section */
6553 curproxy->table.peers.p = NULL;
6554 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006555 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006556 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6557 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006558 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006559 cfgerr++;
6560 }
6561 }
6562
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006563 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006564 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006565 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6566 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6567 "proxy", curproxy->id);
6568 cfgerr++;
6569 goto out_uri_auth_compat;
6570 }
6571
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006572 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006573 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006574 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006575 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006576
Willy Tarreau95fa4692010-02-01 13:05:50 +01006577 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6578 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006579
6580 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006581 uri_auth_compat_req[i++] = "realm";
6582 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6583 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006584
Willy Tarreau95fa4692010-02-01 13:05:50 +01006585 uri_auth_compat_req[i++] = "unless";
6586 uri_auth_compat_req[i++] = "{";
6587 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6588 uri_auth_compat_req[i++] = "}";
6589 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006590
Willy Tarreauff011f22011-01-06 17:51:27 +01006591 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6592 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006593 cfgerr++;
6594 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006595 }
6596
Willy Tarreauff011f22011-01-06 17:51:27 +01006597 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006598
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006599 if (curproxy->uri_auth->auth_realm) {
6600 free(curproxy->uri_auth->auth_realm);
6601 curproxy->uri_auth->auth_realm = NULL;
6602 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006603
6604 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006605 }
6606out_uri_auth_compat:
6607
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006608 /* compile the log format */
6609 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006610 if (curproxy->conf.logformat_string != default_http_log_format &&
6611 curproxy->conf.logformat_string != default_tcp_log_format &&
6612 curproxy->conf.logformat_string != clf_http_log_format)
6613 free(curproxy->conf.logformat_string);
6614 curproxy->conf.logformat_string = NULL;
6615 free(curproxy->conf.lfs_file);
6616 curproxy->conf.lfs_file = NULL;
6617 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006618 }
6619
Willy Tarreau62a61232013-04-12 18:13:46 +02006620 if (curproxy->conf.logformat_string) {
6621 curproxy->conf.args.ctx = ARGC_LOG;
6622 curproxy->conf.args.file = curproxy->conf.lfs_file;
6623 curproxy->conf.args.line = curproxy->conf.lfs_line;
6624 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006625 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006626 curproxy->conf.args.file = NULL;
6627 curproxy->conf.args.line = 0;
6628 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006629
Willy Tarreau62a61232013-04-12 18:13:46 +02006630 if (curproxy->conf.uniqueid_format_string) {
6631 curproxy->conf.args.ctx = ARGC_UIF;
6632 curproxy->conf.args.file = curproxy->conf.uif_file;
6633 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006634 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006635 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006636 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006637 curproxy->conf.args.file = NULL;
6638 curproxy->conf.args.line = 0;
6639 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006640
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006641 /* only now we can check if some args remain unresolved.
6642 * This must be done after the users and groups resolution.
6643 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006644 cfgerr += smp_resolve_args(curproxy);
6645 if (!cfgerr)
6646 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006647
Willy Tarreau2738a142006-07-08 17:28:09 +02006648 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006649 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006650 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006651 (!curproxy->timeout.connect ||
6652 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006653 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006654 " | While not properly invalid, you will certainly encounter various problems\n"
6655 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006656 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006657 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006658 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006659 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006660
Willy Tarreau1fa31262007-12-03 00:36:16 +01006661 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6662 * We must still support older configurations, so let's find out whether those
6663 * parameters have been set or must be copied from contimeouts.
6664 */
6665 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006666 if (!curproxy->timeout.tarpit ||
6667 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006668 /* tarpit timeout not set. We search in the following order:
6669 * default.tarpit, curr.connect, default.connect.
6670 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006671 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006672 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006673 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006674 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006675 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006676 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006677 }
6678 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006679 (!curproxy->timeout.queue ||
6680 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006681 /* queue timeout not set. We search in the following order:
6682 * default.queue, curr.connect, default.connect.
6683 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006684 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006685 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006686 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006687 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006688 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006689 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006690 }
6691 }
6692
Willy Tarreau1620ec32011-08-06 17:05:02 +02006693 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006694 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6695 curproxy->check_req = (char *)malloc(curproxy->check_len);
6696 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006697 }
6698
Willy Tarreau215663d2014-06-13 18:30:23 +02006699 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6700 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6701 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6702 proxy_type_str(curproxy), curproxy->id);
6703 err_code |= ERR_WARN;
6704 }
6705
Willy Tarreau193b8c62012-11-22 00:17:38 +01006706 /* ensure that cookie capture length is not too large */
6707 if (curproxy->capture_len >= global.tune.cookie_len) {
6708 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6709 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6710 err_code |= ERR_WARN;
6711 curproxy->capture_len = global.tune.cookie_len - 1;
6712 }
6713
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006714 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006715 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006716 curproxy->req_cap_pool = create_pool("ptrcap",
6717 curproxy->nb_req_cap * sizeof(char *),
6718 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006719 }
6720
6721 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006722 curproxy->rsp_cap_pool = create_pool("ptrcap",
6723 curproxy->nb_rsp_cap * sizeof(char *),
6724 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006725 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006726
Willy Tarreaubaaee002006-06-26 02:48:02 +02006727 /* first, we will invert the servers list order */
6728 newsrv = NULL;
6729 while (curproxy->srv) {
6730 struct server *next;
6731
6732 next = curproxy->srv->next;
6733 curproxy->srv->next = newsrv;
6734 newsrv = curproxy->srv;
6735 if (!next)
6736 break;
6737 curproxy->srv = next;
6738 }
6739
Willy Tarreau17edc812014-01-03 12:14:34 +01006740 /* Check that no server name conflicts. This causes trouble in the stats.
6741 * We only emit a warning for the first conflict affecting each server,
6742 * in order to avoid combinatory explosion if all servers have the same
6743 * name. We do that only for servers which do not have an explicit ID,
6744 * because these IDs were made also for distinguishing them and we don't
6745 * want to annoy people who correctly manage them.
6746 */
6747 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6748 struct server *other_srv;
6749
6750 if (newsrv->puid)
6751 continue;
6752
6753 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6754 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6755 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6756 newsrv->conf.file, newsrv->conf.line,
6757 proxy_type_str(curproxy), curproxy->id,
6758 newsrv->id, other_srv->conf.line);
6759 break;
6760 }
6761 }
6762 }
6763
Willy Tarreaudd701652010-05-25 23:03:02 +02006764 /* assign automatic UIDs to servers which don't have one yet */
6765 next_id = 1;
6766 newsrv = curproxy->srv;
6767 while (newsrv != NULL) {
6768 if (!newsrv->puid) {
6769 /* server ID not set, use automatic numbering with first
6770 * spare entry starting with next_svid.
6771 */
6772 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6773 newsrv->conf.id.key = newsrv->puid = next_id;
6774 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6775 }
6776 next_id++;
6777 newsrv = newsrv->next;
6778 }
6779
Willy Tarreau20697042007-11-15 23:26:18 +01006780 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006781 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006782
Willy Tarreau62c3be22012-01-20 13:12:32 +01006783 /*
6784 * If this server supports a maxconn parameter, it needs a dedicated
6785 * tasks to fill the emptied slots when a connection leaves.
6786 * Also, resolve deferred tracking dependency if needed.
6787 */
6788 newsrv = curproxy->srv;
6789 while (newsrv != NULL) {
6790 if (newsrv->minconn > newsrv->maxconn) {
6791 /* Only 'minconn' was specified, or it was higher than or equal
6792 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6793 * this will avoid further useless expensive computations.
6794 */
6795 newsrv->maxconn = newsrv->minconn;
6796 } else if (newsrv->maxconn && !newsrv->minconn) {
6797 /* minconn was not specified, so we set it to maxconn */
6798 newsrv->minconn = newsrv->maxconn;
6799 }
6800
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006801#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006802 if (newsrv->use_ssl || newsrv->check.use_ssl)
6803 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006804#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006805
Willy Tarreau2f075e92013-12-03 11:11:34 +01006806 /* set the check type on the server */
6807 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6808
Willy Tarreau62c3be22012-01-20 13:12:32 +01006809 if (newsrv->trackit) {
6810 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006811 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006812 char *pname, *sname;
6813
6814 pname = newsrv->trackit;
6815 sname = strrchr(pname, '/');
6816
6817 if (sname)
6818 *sname++ = '\0';
6819 else {
6820 sname = pname;
6821 pname = NULL;
6822 }
6823
6824 if (pname) {
6825 px = findproxy(pname, PR_CAP_BE);
6826 if (!px) {
6827 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6828 proxy_type_str(curproxy), curproxy->id,
6829 newsrv->id, pname);
6830 cfgerr++;
6831 goto next_srv;
6832 }
6833 } else
6834 px = curproxy;
6835
6836 srv = findserver(px, sname);
6837 if (!srv) {
6838 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6839 proxy_type_str(curproxy), curproxy->id,
6840 newsrv->id, sname);
6841 cfgerr++;
6842 goto next_srv;
6843 }
6844
Willy Tarreau32091232014-05-16 13:52:00 +02006845 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6846 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6847 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006848 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006849 "tracking as it does not have any check nor agent enabled.\n",
6850 proxy_type_str(curproxy), curproxy->id,
6851 newsrv->id, px->id, srv->id);
6852 cfgerr++;
6853 goto next_srv;
6854 }
6855
6856 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6857
6858 if (loop) {
6859 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6860 "belongs to a tracking chain looping back to %s/%s.\n",
6861 proxy_type_str(curproxy), curproxy->id,
6862 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006863 cfgerr++;
6864 goto next_srv;
6865 }
6866
6867 if (curproxy != px &&
6868 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6869 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6870 "tracking: disable-on-404 option inconsistency.\n",
6871 proxy_type_str(curproxy), curproxy->id,
6872 newsrv->id, px->id, srv->id);
6873 cfgerr++;
6874 goto next_srv;
6875 }
6876
6877 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006878 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006879 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006880 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006881 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006882 }
6883
6884 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006885 newsrv->tracknext = srv->trackers;
6886 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006887
6888 free(newsrv->trackit);
6889 newsrv->trackit = NULL;
6890 }
6891 next_srv:
6892 newsrv = newsrv->next;
6893 }
6894
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006895 /* We have to initialize the server lookup mechanism depending
6896 * on what LB algorithm was choosen.
6897 */
6898
6899 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6900 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6901 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006902 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6903 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6904 init_server_map(curproxy);
6905 } else {
6906 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6907 fwrr_init_server_groups(curproxy);
6908 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006909 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006910
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006911 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006912 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6913 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6914 fwlc_init_server_tree(curproxy);
6915 } else {
6916 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6917 fas_init_server_tree(curproxy);
6918 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006919 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006920
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006921 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006922 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6923 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6924 chash_init_server_tree(curproxy);
6925 } else {
6926 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6927 init_server_map(curproxy);
6928 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006929 break;
6930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006931
6932 if (curproxy->options & PR_O_LOGASAP)
6933 curproxy->to_log &= ~LW_BYTES;
6934
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006935 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006936 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006937 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6938 proxy_type_str(curproxy), curproxy->id);
6939 err_code |= ERR_WARN;
6940 }
6941
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006942 if (curproxy->mode != PR_MODE_HTTP) {
6943 int optnum;
6944
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006945 if (curproxy->uri_auth) {
6946 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6947 proxy_type_str(curproxy), curproxy->id);
6948 err_code |= ERR_WARN;
6949 curproxy->uri_auth = NULL;
6950 }
6951
Willy Tarreau87cf5142011-08-19 22:57:24 +02006952 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006953 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6954 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6955 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006956 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006957 }
6958
6959 if (curproxy->options & PR_O_ORGTO) {
6960 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6961 "originalto", proxy_type_str(curproxy), curproxy->id);
6962 err_code |= ERR_WARN;
6963 curproxy->options &= ~PR_O_ORGTO;
6964 }
6965
6966 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6967 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6968 (curproxy->cap & cfg_opts[optnum].cap) &&
6969 (curproxy->options & cfg_opts[optnum].val)) {
6970 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6971 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6972 err_code |= ERR_WARN;
6973 curproxy->options &= ~cfg_opts[optnum].val;
6974 }
6975 }
6976
6977 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6978 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6979 (curproxy->cap & cfg_opts2[optnum].cap) &&
6980 (curproxy->options2 & cfg_opts2[optnum].val)) {
6981 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6982 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6983 err_code |= ERR_WARN;
6984 curproxy->options2 &= ~cfg_opts2[optnum].val;
6985 }
6986 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006987
Pieter Baauwd551fb52013-05-08 22:49:23 +02006988#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006989 if (curproxy->conn_src.bind_hdr_occ) {
6990 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006991 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006992 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006993 err_code |= ERR_WARN;
6994 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006995#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006996 }
6997
Willy Tarreaubaaee002006-06-26 02:48:02 +02006998 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006999 * ensure that we're not cross-dressing a TCP server into HTTP.
7000 */
7001 newsrv = curproxy->srv;
7002 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007003 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007004 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7005 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007006 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007007 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007008
Willy Tarreau0cec3312011-10-31 13:49:26 +01007009 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7010 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7011 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7012 err_code |= ERR_WARN;
7013 }
7014
Willy Tarreauc93cd162014-05-13 15:54:22 +02007015 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007016 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7017 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7018 err_code |= ERR_WARN;
7019 }
7020
Pieter Baauwd551fb52013-05-08 22:49:23 +02007021#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007022 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7023 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007024 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 +01007025 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007026 err_code |= ERR_WARN;
7027 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007028#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007029 newsrv = newsrv->next;
7030 }
7031
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007032 /* check if we have a frontend with "tcp-request content" looking at L7
7033 * with no inspect-delay
7034 */
7035 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7036 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7037 if (trule->action == TCP_ACT_CAPTURE &&
7038 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7039 break;
7040 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7041 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7042 break;
7043 }
7044
7045 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7046 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7047 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7048 " This means that these rules will randomly find their contents. This can be fixed by"
7049 " setting the tcp-request inspect-delay.\n",
7050 proxy_type_str(curproxy), curproxy->id);
7051 err_code |= ERR_WARN;
7052 }
7053 }
7054
Willy Tarreauc1a21672009-08-16 22:37:44 +02007055 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007056 if (!curproxy->accept)
7057 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007058
Willy Tarreauc1a21672009-08-16 22:37:44 +02007059 if (curproxy->tcp_req.inspect_delay ||
7060 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007061 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007062
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007063 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007064 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007065 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007066 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007067
7068 /* both TCP and HTTP must check switching rules */
7069 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7070 }
7071
7072 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007073 if (curproxy->tcp_req.inspect_delay ||
7074 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7075 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7076
Emeric Brun97679e72010-09-23 17:56:44 +02007077 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7078 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7079
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007080 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007081 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007082 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007083 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007084
7085 /* If the backend does requires RDP cookie persistence, we have to
7086 * enable the corresponding analyser.
7087 */
7088 if (curproxy->options2 & PR_O2_RDPC_PRST)
7089 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7090 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007091 }
7092
7093 /***********************************************************/
7094 /* At this point, target names have already been resolved. */
7095 /***********************************************************/
7096
7097 /* Check multi-process mode compatibility */
7098
7099 if (global.nbproc > 1 && global.stats_fe) {
7100 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7101 unsigned long mask;
7102
7103 mask = nbits(global.nbproc);
7104 if (global.stats_fe->bind_proc)
7105 mask &= global.stats_fe->bind_proc;
7106
7107 if (bind_conf->bind_proc)
7108 mask &= bind_conf->bind_proc;
7109
7110 /* stop here if more than one process is used */
David Carlier6de4c2f2015-07-02 07:00:17 +00007111 if (my_popcountl(mask) > 1)
Willy Tarreau91b00c22014-09-16 13:41:21 +02007112 break;
7113 }
7114 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7115 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");
7116 }
7117 }
7118
7119 /* Make each frontend inherit bind-process from its listeners when not specified. */
7120 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7121 if (curproxy->bind_proc)
7122 continue;
7123
7124 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7125 unsigned long mask;
7126
Willy Tarreau01760ad2015-05-04 21:57:58 +02007127 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007128 curproxy->bind_proc |= mask;
7129 }
7130
7131 if (!curproxy->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007132 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007133 }
7134
7135 if (global.stats_fe) {
7136 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7137 unsigned long mask;
7138
Willy Tarreau01760ad2015-05-04 21:57:58 +02007139 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007140 global.stats_fe->bind_proc |= mask;
7141 }
7142 if (!global.stats_fe->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007143 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007144 }
7145
Willy Tarreaub3228c82014-10-01 20:50:17 +02007146 /* propagate bindings from frontends to backends. Don't do it if there
7147 * are any fatal errors as we must not call it with unresolved proxies.
7148 */
7149 if (!cfgerr) {
7150 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7151 if (curproxy->cap & PR_CAP_FE)
7152 propagate_processes(curproxy, NULL);
7153 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007154 }
7155
7156 /* Bind each unbound backend to all processes when not specified. */
7157 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7158 if (curproxy->bind_proc)
7159 continue;
Willy Tarreau01760ad2015-05-04 21:57:58 +02007160 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007161 }
7162
7163 /*******************************************************/
7164 /* At this step, all proxies have a non-null bind_proc */
7165 /*******************************************************/
7166
7167 /* perform the final checks before creating tasks */
7168
7169 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7170 struct listener *listener;
7171 unsigned int next_id;
7172 int nbproc;
7173
David Carlier6de4c2f2015-07-02 07:00:17 +00007174 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007175
Emeric Brunc52962f2012-11-15 18:28:02 +01007176#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007177 /* Configure SSL for each bind line.
7178 * Note: if configuration fails at some point, the ->ctx member
7179 * remains NULL so that listeners can later detach.
7180 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007181 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007182 int alloc_ctx;
7183
Emeric Brunc52962f2012-11-15 18:28:02 +01007184 if (!bind_conf->is_ssl) {
7185 if (bind_conf->default_ctx) {
7186 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7187 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7188 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007189 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007190 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007191 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007192 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007193 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007194 cfgerr++;
7195 continue;
7196 }
7197
Emeric Brun8dc60392014-05-09 13:52:00 +02007198 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007199 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007200 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7201 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");
7202 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007203 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007204 cfgerr++;
7205 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007206 }
7207
Emeric Brunfc0421f2012-09-07 17:30:07 +02007208 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007209 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007210 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007211#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007212
Willy Tarreaue6b98942007-10-29 01:09:36 +01007213 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007214 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007215 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007216 if (!listener->luid) {
7217 /* listener ID not set, use automatic numbering with first
7218 * spare entry starting with next_luid.
7219 */
7220 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7221 listener->conf.id.key = listener->luid = next_id;
7222 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007223 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007224 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007225
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007226 /* enable separate counters */
7227 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7228 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007229 if (!listener->name)
7230 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007231 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007232
Willy Tarreaue6b98942007-10-29 01:09:36 +01007233 if (curproxy->options & PR_O_TCP_NOLING)
7234 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007235 if (!listener->maxconn)
7236 listener->maxconn = curproxy->maxconn;
7237 if (!listener->backlog)
7238 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007239 if (!listener->maxaccept)
7240 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7241
7242 /* we want to have an optimal behaviour on single process mode to
7243 * maximize the work at once, but in multi-process we want to keep
7244 * some fairness between processes, so we target half of the max
7245 * number of events to be balanced over all the processes the proxy
7246 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7247 * used to disable the limit.
7248 */
7249 if (listener->maxaccept > 0) {
7250 if (nbproc > 1)
7251 listener->maxaccept = (listener->maxaccept + 1) / 2;
7252 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7253 }
7254
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007255 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007256 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007257 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007258 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007259
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007260 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7261 listener->options |= LI_O_TCP_RULES;
7262
Willy Tarreaude3041d2010-05-31 10:56:17 +02007263 if (curproxy->mon_mask.s_addr)
7264 listener->options |= LI_O_CHK_MONNET;
7265
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007266 /* smart accept mode is automatic in HTTP mode */
7267 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007268 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007269 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7270 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007271 }
7272
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007273 /* Release unused SSL configs */
7274 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7275 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007276 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007277#ifdef USE_OPENSSL
7278 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007279 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007280 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007281 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007282 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007283#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007284 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007285
Willy Tarreau102df612014-05-07 23:56:38 +02007286 if (nbproc > 1) {
7287 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007288 int count, maxproc = 0;
7289
7290 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carlier6de4c2f2015-07-02 07:00:17 +00007291 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreau036a83e2014-09-16 15:11:04 +02007292 if (count > maxproc)
7293 maxproc = count;
7294 }
7295 /* backends have 0, frontends have 1 or more */
7296 if (maxproc != 1)
7297 Warning("Proxy '%s': in multi-process mode, stats will be"
7298 " limited to process assigned to the current request.\n",
7299 curproxy->id);
7300
Willy Tarreau102df612014-05-07 23:56:38 +02007301 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7302 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7303 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007304 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007305 }
Willy Tarreau102df612014-05-07 23:56:38 +02007306 if (curproxy->appsession_name) {
7307 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7308 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007309 }
Willy Tarreau102df612014-05-07 23:56:38 +02007310 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7311 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7312 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007313 }
7314 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007315
7316 /* create the task associated with the proxy */
7317 curproxy->task = task_new();
7318 if (curproxy->task) {
7319 curproxy->task->context = curproxy;
7320 curproxy->task->process = manage_proxy;
7321 /* no need to queue, it will be done automatically if some
7322 * listener gets limited.
7323 */
7324 curproxy->task->expire = TICK_ETERNITY;
7325 } else {
7326 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7327 curproxy->id);
7328 cfgerr++;
7329 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007330 }
7331
Willy Tarreaufbb78422011-06-05 15:38:35 +02007332 /* automatically compute fullconn if not set. We must not do it in the
7333 * loop above because cross-references are not yet fully resolved.
7334 */
7335 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7336 /* If <fullconn> is not set, let's set it to 10% of the sum of
7337 * the possible incoming frontend's maxconns.
7338 */
7339 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7340 struct proxy *fe;
7341 int total = 0;
7342
7343 /* sum up the number of maxconns of frontends which
7344 * reference this backend at least once or which are
7345 * the same one ('listen').
7346 */
7347 for (fe = proxy; fe; fe = fe->next) {
7348 struct switching_rule *rule;
7349 struct hdr_exp *exp;
7350 int found = 0;
7351
7352 if (!(fe->cap & PR_CAP_FE))
7353 continue;
7354
7355 if (fe == curproxy) /* we're on a "listen" instance */
7356 found = 1;
7357
7358 if (fe->defbe.be == curproxy) /* "default_backend" */
7359 found = 1;
7360
7361 /* check if a "use_backend" rule matches */
7362 if (!found) {
7363 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007364 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007365 found = 1;
7366 break;
7367 }
7368 }
7369 }
7370
7371 /* check if a "reqsetbe" rule matches */
7372 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7373 if (exp->action == ACT_SETBE &&
7374 (struct proxy *)exp->replace == curproxy) {
7375 found = 1;
7376 break;
7377 }
7378 }
7379
7380 /* now we've checked all possible ways to reference a backend
7381 * from a frontend.
7382 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007383 if (!found)
7384 continue;
7385 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007386 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007387 /* we have the sum of the maxconns in <total>. We only
7388 * keep 10% of that sum to set the default fullconn, with
7389 * a hard minimum of 1 (to avoid a divide by zero).
7390 */
7391 curproxy->fullconn = (total + 9) / 10;
7392 if (!curproxy->fullconn)
7393 curproxy->fullconn = 1;
7394 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007395 }
7396
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007397 /*
7398 * Recount currently required checks.
7399 */
7400
7401 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7402 int optnum;
7403
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007404 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7405 if (curproxy->options & cfg_opts[optnum].val)
7406 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007407
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007408 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7409 if (curproxy->options2 & cfg_opts2[optnum].val)
7410 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007411 }
7412
Willy Tarreaucdb5e922015-05-01 19:12:05 +02007413 /* compute the required process bindings for the peers */
7414 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7415 if (curproxy->table.peers.p)
7416 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7417
Willy Tarreau122541c2011-09-07 21:24:49 +02007418 if (peers) {
7419 struct peers *curpeers = peers, **last;
7420 struct peer *p, *pb;
7421
Willy Tarreauab0419d2015-05-01 19:15:17 +02007422 /* Remove all peers sections which don't have a valid listener,
7423 * which are not used by any table, or which are bound to more
7424 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02007425 */
7426 last = &peers;
7427 while (*last) {
7428 curpeers = *last;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007429
7430 if (curpeers->state == PR_STSTOPPED) {
7431 /* the "disabled" keyword was present */
7432 if (curpeers->peers_fe)
7433 stop_proxy(curpeers->peers_fe);
7434 curpeers->peers_fe = NULL;
7435 }
7436 else if (!curpeers->peers_fe) {
7437 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7438 curpeers->id, localpeer);
7439 }
David Carlier6de4c2f2015-07-02 07:00:17 +00007440 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreauab0419d2015-05-01 19:15:17 +02007441 /* either it's totally stopped or too much used */
7442 if (curpeers->peers_fe->bind_proc) {
7443 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreaua5d7d072015-05-04 21:48:51 +02007444 "running in different processes (%d different ones). "
7445 "Check global.nbproc and all tables' bind-process "
David Carlier6de4c2f2015-07-02 07:00:17 +00007446 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreauab0419d2015-05-01 19:15:17 +02007447 cfgerr++;
7448 }
7449 stop_proxy(curpeers->peers_fe);
7450 curpeers->peers_fe = NULL;
7451 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02007452 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007453 last = &curpeers->next;
7454 continue;
7455 }
7456
Willy Tarreau34d05b02015-05-01 20:02:17 +02007457 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007458 p = curpeers->remote;
7459 while (p) {
7460 pb = p->next;
7461 free(p->id);
7462 free(p);
7463 p = pb;
7464 }
7465
7466 /* Destroy and unlink this curpeers section.
7467 * Note: curpeers is backed up into *last.
7468 */
7469 free(curpeers->id);
7470 curpeers = curpeers->next;
7471 free(*last);
7472 *last = curpeers;
7473 }
7474 }
7475
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007476 /* initialize stick-tables on backend capable proxies. This must not
7477 * be done earlier because the data size may be discovered while parsing
7478 * other proxies.
7479 */
7480 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7481 if (curproxy->state == PR_STSTOPPED)
7482 continue;
7483
7484 if (!stktable_init(&curproxy->table)) {
7485 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7486 cfgerr++;
7487 }
7488 }
7489
Willy Tarreau34eb6712011-10-24 18:15:04 +02007490 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007491 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007492 MEM_F_SHARED);
7493
Willy Tarreaubb925012009-07-23 13:36:36 +02007494 if (cfgerr > 0)
7495 err_code |= ERR_ALERT | ERR_FATAL;
7496 out:
7497 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007498}
7499
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007500/*
7501 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7502 * parsing sessions.
7503 */
7504void cfg_register_keywords(struct cfg_kw_list *kwl)
7505{
7506 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7507}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007508
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007509/*
7510 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7511 */
7512void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7513{
7514 LIST_DEL(&kwl->list);
7515 LIST_INIT(&kwl->list);
7516}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007517
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007518/* this function register new section in the haproxy configuration file.
7519 * <section_name> is the name of this new section and <section_parser>
7520 * is the called parser. If two section declaration have the same name,
7521 * only the first declared is used.
7522 */
7523int cfg_register_section(char *section_name,
7524 int (*section_parser)(const char *, int, char **, int))
7525{
7526 struct cfg_section *cs;
7527
7528 cs = calloc(1, sizeof(*cs));
7529 if (!cs) {
7530 Alert("register section '%s': out of memory.\n", section_name);
7531 return 0;
7532 }
7533
7534 cs->section_name = section_name;
7535 cs->section_parser = section_parser;
7536
7537 LIST_ADDQ(&sections, &cs->list);
7538
7539 return 1;
7540}
7541
Willy Tarreaubaaee002006-06-26 02:48:02 +02007542/*
7543 * Local variables:
7544 * c-indent-level: 8
7545 * c-basic-offset: 8
7546 * End:
7547 */