blob: 9812ec202c94e668fa5fe4b962856e0a0f799384 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté2c8d7002014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau1c3a6122015-05-01 15:37:53 +0200154 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
283 ss = *ss2;
284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200543 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 if (!strcmp(args[0], "global")) { /* new section */
546 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200549 else if (!strcmp(args[0], "ca-base")) {
550#ifdef USE_OPENSSL
551 if (global.ca_base != NULL) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.ca_base = strdup(args[1]);
562#else
563 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566#endif
567 }
568 else if (!strcmp(args[0], "crt-base")) {
569#ifdef USE_OPENSSL
570 if (global.crt_base != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT;
573 goto out;
574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.crt_base = strdup(args[1]);
581#else
582 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585#endif
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 else if (!strcmp(args[0], "daemon")) {
588 global.mode |= MODE_DAEMON;
589 }
590 else if (!strcmp(args[0], "debug")) {
591 global.mode |= MODE_DEBUG;
592 }
593 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100594 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200596 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100602 else if (!strcmp(args[0], "nosplice")) {
603 global.tune.options &= ~GTUNE_USE_SPLICE;
604 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605 else if (!strcmp(args[0], "nogetaddrinfo")) {
606 global.tune.options &= ~GTUNE_USE_GAI;
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "quiet")) {
609 global.mode |= MODE_QUIET;
610 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200611 else if (!strcmp(args[0], "tune.maxpollevents")) {
612 if (global.tune.maxpollevents != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200621 }
622 global.tune.maxpollevents = atol(args[1]);
623 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100624 else if (!strcmp(args[0], "tune.maxaccept")) {
625 if (global.tune.maxaccept != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100634 }
635 global.tune.maxaccept = atol(args[1]);
636 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200637 else if (!strcmp(args[0], "tune.chksize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.chksize = atol(args[1]);
644 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200645#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200646 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
647 global.tune.sslprivatecache = 1;
648 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100649 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.sslcachesize = atol(args[1]);
656 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100657 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
658 unsigned int ssllifetime;
659 const char *res;
660
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666
667 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
668 if (res) {
669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
670 file, linenum, *res, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 global.tune.ssllifetime = ssllifetime;
676 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100677 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.ssl_max_record = atol(args[1]);
684 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200685 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.ssl_default_dh_param = atol(args[1]);
692 if (global.tune.ssl_default_dh_param < 1024) {
693 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200698#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200699 else if (!strcmp(args[0], "tune.bufsize")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.bufsize = atol(args[1]);
706 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
707 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100708 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100709 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200710 }
711 else if (!strcmp(args[0], "tune.maxrewrite")) {
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 global.tune.maxrewrite = atol(args[1]);
718 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
719 global.tune.maxrewrite = global.tune.bufsize / 2;
720 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100721 else if (!strcmp(args[0], "tune.idletimer")) {
722 unsigned int idle;
723 const char *res;
724
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730
731 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
732 if (res) {
733 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
734 file, linenum, *res, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738
739 if (idle > 65535) {
740 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.idle_timer = idle;
745 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100746 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
747 if (global.tune.client_rcvbuf != 0) {
748 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
749 err_code |= ERR_ALERT;
750 goto out;
751 }
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757 global.tune.client_rcvbuf = atol(args[1]);
758 }
759 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
760 if (global.tune.server_rcvbuf != 0) {
761 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT;
763 goto out;
764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.server_rcvbuf = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "tune.sndbuf.client")) {
773 if (global.tune.client_sndbuf != 0) {
774 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT;
776 goto out;
777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.client_sndbuf = atol(args[1]);
784 }
785 else if (!strcmp(args[0], "tune.sndbuf.server")) {
786 if (global.tune.server_sndbuf != 0) {
787 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT;
789 goto out;
790 }
791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.tune.server_sndbuf = atol(args[1]);
797 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200798 else if (!strcmp(args[0], "tune.pipesize")) {
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.pipesize = atol(args[1]);
805 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100806 else if (!strcmp(args[0], "tune.http.cookielen")) {
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.cookie_len = atol(args[1]) + 1;
813 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200814 else if (!strcmp(args[0], "tune.http.maxhdr")) {
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.max_http_hdr = atol(args[1]);
821 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100822 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
823#ifdef USE_ZLIB
824 if (*args[1]) {
825 global.tune.zlibmemlevel = atoi(args[1]);
826 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 } else {
833 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
834 file, linenum, args[0]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838#else
839 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842#endif
843 }
844 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
845#ifdef USE_ZLIB
846 if (*args[1]) {
847 global.tune.zlibwindowsize = atoi(args[1]);
848 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
849 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\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' expects a numeric value between 8 and 15\n",
856 file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860#else
861 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864#endif
865 }
William Lallemandf3747832012-11-09 12:33:10 +0100866 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
867 if (*args[1]) {
868 global.tune.comp_maxlevel = atoi(args[1]);
869 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
870 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
871 file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 } else {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 else if (!strcmp(args[0], "uid")) {
883 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200884 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT;
886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 global.uid = atol(args[1]);
894 }
895 else if (!strcmp(args[0], "gid")) {
896 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200897 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 global.gid = atol(args[1]);
907 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200908 /* user/group name handling */
909 else if (!strcmp(args[0], "user")) {
910 struct passwd *ha_user;
911 if (global.uid != 0) {
912 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200913 err_code |= ERR_ALERT;
914 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200915 }
916 errno = 0;
917 ha_user = getpwnam(args[1]);
918 if (ha_user != NULL) {
919 global.uid = (int)ha_user->pw_uid;
920 }
921 else {
922 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 +0200923 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200924 }
925 }
926 else if (!strcmp(args[0], "group")) {
927 struct group *ha_group;
928 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200929 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT;
931 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200932 }
933 errno = 0;
934 ha_group = getgrnam(args[1]);
935 if (ha_group != NULL) {
936 global.gid = (int)ha_group->gr_gid;
937 }
938 else {
939 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 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200941 }
942 }
943 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100951 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
952 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
953 file, linenum, args[0], LONGBITS, global.nbproc);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (!strcmp(args[0], "maxconn")) {
959 if (global.maxconn != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT;
962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 global.maxconn = atol(args[1]);
970#ifdef SYSTEM_MAXCONN
971 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
972 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);
973 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200974 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 }
976#endif /* SYSTEM_MAXCONN */
977 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200978 else if (!strcmp(args[0], "maxsslconn")) {
979#ifdef USE_OPENSSL
980 if (*(args[1]) == 0) {
981 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984 }
985 global.maxsslconn = atol(args[1]);
986#else
Emeric Brun0914df82012-10-02 18:45:42 +0200987 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200990#endif
991 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100992 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
993#ifdef USE_OPENSSL
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999 free(global.listen_default_ciphers);
1000 global.listen_default_ciphers = strdup(args[1]);
1001#else
1002 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005#endif
1006 }
1007 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1008#ifdef USE_OPENSSL
1009 if (*(args[1]) == 0) {
1010 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 free(global.connect_default_ciphers);
1015 global.connect_default_ciphers = strdup(args[1]);
1016#else
1017 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020#endif
1021 }
Emeric Brun850efd52014-01-29 12:24:34 +01001022 else if (!strcmp(args[0], "ssl-server-verify")) {
1023 if (*(args[1]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 if (strcmp(args[1],"none") == 0)
1029 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1030 else if (strcmp(args[1],"required") == 0)
1031 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1032 else {
1033 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036 }
1037 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001038 else if (!strcmp(args[0], "maxconnrate")) {
1039 if (global.cps_lim != 0) {
1040 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT;
1042 goto out;
1043 }
1044 if (*(args[1]) == 0) {
1045 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
1048 }
1049 global.cps_lim = atol(args[1]);
1050 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001051 else if (!strcmp(args[0], "maxsessrate")) {
1052 if (global.sps_lim != 0) {
1053 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1054 err_code |= ERR_ALERT;
1055 goto out;
1056 }
1057 if (*(args[1]) == 0) {
1058 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 global.sps_lim = atol(args[1]);
1063 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001064 else if (!strcmp(args[0], "maxsslrate")) {
1065 if (global.ssl_lim != 0) {
1066 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1067 err_code |= ERR_ALERT;
1068 goto out;
1069 }
1070 if (*(args[1]) == 0) {
1071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 global.ssl_lim = atol(args[1]);
1076 }
William Lallemandd85f9172012-11-09 17:05:39 +01001077 else if (!strcmp(args[0], "maxcomprate")) {
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
1082 }
1083 global.comp_rate_lim = atoi(args[1]) * 1024;
1084 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001085 else if (!strcmp(args[0], "maxpipes")) {
1086 if (global.maxpipes != 0) {
1087 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT;
1089 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001090 }
1091 if (*(args[1]) == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001095 }
1096 global.maxpipes = atol(args[1]);
1097 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001098 else if (!strcmp(args[0], "maxzlibmem")) {
1099 if (*(args[1]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
William Lallemande3a7d992012-11-20 11:25:20 +01001104 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001105 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001106 else if (!strcmp(args[0], "maxcompcpuusage")) {
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001113 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001114 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT | ERR_FATAL;
1116 goto out;
1117 }
1118}
1119
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 else if (!strcmp(args[0], "ulimit-n")) {
1121 if (global.rlimit_nofile != 0) {
1122 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 }
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 global.rlimit_nofile = atol(args[1]);
1132 }
1133 else if (!strcmp(args[0], "chroot")) {
1134 if (global.chroot != NULL) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
1137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 global.chroot = strdup(args[1]);
1145 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001146 else if (!strcmp(args[0], "description")) {
1147 int i, len=0;
1148 char *d;
1149
1150 if (!*args[1]) {
1151 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1152 file, linenum, args[0]);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto out;
1155 }
1156
Willy Tarreau348acfe2014-04-14 15:00:39 +02001157 for (i = 1; *args[i]; i++)
1158 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001159
1160 if (global.desc)
1161 free(global.desc);
1162
1163 global.desc = d = (char *)calloc(1, len);
1164
Willy Tarreau348acfe2014-04-14 15:00:39 +02001165 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1166 for (i = 2; *args[i]; i++)
1167 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001168 }
1169 else if (!strcmp(args[0], "node")) {
1170 int i;
1171 char c;
1172
1173 for (i=0; args[1][i]; i++) {
1174 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001175 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1176 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001177 break;
1178 }
1179
1180 if (!i || args[1][i]) {
1181 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1182 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1183 file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 if (global.node)
1189 free(global.node);
1190
1191 global.node = strdup(args[1]);
1192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 else if (!strcmp(args[0], "pidfile")) {
1194 if (global.pidfile != NULL) {
1195 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT;
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 }
1199 if (*(args[1]) == 0) {
1200 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 global.pidfile = strdup(args[1]);
1205 }
Emeric Bruned760922010-10-22 17:59:25 +02001206 else if (!strcmp(args[0], "unix-bind")) {
1207 int cur_arg = 1;
1208 while (*(args[cur_arg])) {
1209 if (!strcmp(args[cur_arg], "prefix")) {
1210 if (global.unix_bind.prefix != NULL) {
1211 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1212 err_code |= ERR_ALERT;
1213 cur_arg += 2;
1214 continue;
1215 }
1216
1217 if (*(args[cur_arg+1]) == 0) {
1218 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1223 cur_arg += 2;
1224 continue;
1225 }
1226
1227 if (!strcmp(args[cur_arg], "mode")) {
1228
1229 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1230 cur_arg += 2;
1231 continue;
1232 }
1233
1234 if (!strcmp(args[cur_arg], "uid")) {
1235
1236 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1237 cur_arg += 2;
1238 continue;
1239 }
1240
1241 if (!strcmp(args[cur_arg], "gid")) {
1242
1243 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1244 cur_arg += 2;
1245 continue;
1246 }
1247
1248 if (!strcmp(args[cur_arg], "user")) {
1249 struct passwd *user;
1250
1251 user = getpwnam(args[cur_arg + 1]);
1252 if (!user) {
1253 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1254 file, linenum, args[0], args[cur_arg + 1 ]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258
1259 global.unix_bind.ux.uid = user->pw_uid;
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (!strcmp(args[cur_arg], "group")) {
1265 struct group *group;
1266
1267 group = getgrnam(args[cur_arg + 1]);
1268 if (!group) {
1269 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\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.gid = group->gr_gid;
1276 cur_arg += 2;
1277 continue;
1278 }
1279
Willy Tarreaub48f9582011-09-05 01:17:06 +02001280 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001281 file, linenum, args[0]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285 }
William Lallemand0f99e342011-10-12 17:50:54 +02001286 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1287 /* delete previous herited or defined syslog servers */
1288 struct logsrv *back;
1289 struct logsrv *tmp;
1290
1291 if (*(args[1]) != 0) {
1292 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
1296
1297 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1298 LIST_DEL(&tmp->list);
1299 free(tmp);
1300 }
1301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001303 struct sockaddr_storage *sk;
1304 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001305 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001306 int arg = 0;
1307 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001308
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 if (*(args[1]) == 0 || *(args[2]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313 }
William Lallemand0f99e342011-10-12 17:50:54 +02001314
1315 logsrv = calloc(1, sizeof(struct logsrv));
1316
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001317 /* just after the address, a length may be specified */
1318 if (strcmp(args[arg+2], "len") == 0) {
1319 len = atoi(args[arg+3]);
1320 if (len < 80 || len > 65535) {
1321 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1322 file, linenum, args[arg+3]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326 logsrv->maxlen = len;
1327
1328 /* skip these two args */
1329 arg += 2;
1330 }
1331 else
1332 logsrv->maxlen = MAX_SYSLOG_LEN;
1333
1334 if (logsrv->maxlen > global.max_syslog_len) {
1335 global.max_syslog_len = logsrv->maxlen;
1336 logline = realloc(logline, global.max_syslog_len + 1);
1337 }
1338
1339 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001340 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001341 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001343 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 }
1345
William Lallemand0f99e342011-10-12 17:50:54 +02001346 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001347 if (*(args[arg+3])) {
1348 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001349 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001350 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001352 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
1354 }
1355
William Lallemand0f99e342011-10-12 17:50:54 +02001356 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001357 if (*(args[arg+4])) {
1358 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001359 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001360 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001361 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001362 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001363 }
1364 }
1365
Willy Tarreau902636f2013-03-10 19:44:48 +01001366 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001367 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001368 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001369 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001370 free(logsrv);
1371 goto out;
1372 }
1373 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001374
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001375 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001376 if (port1 != port2) {
1377 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1378 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001379 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001380 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001381 goto out;
1382 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001383
William Lallemand0f99e342011-10-12 17:50:54 +02001384 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001385 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001386 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388
William Lallemand0f99e342011-10-12 17:50:54 +02001389 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001390 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001391 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1392 char *name;
1393 int len;
1394
1395 if (global.log_send_hostname != NULL) {
1396 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1397 err_code |= ERR_ALERT;
1398 goto out;
1399 }
1400
1401 if (*(args[1]))
1402 name = args[1];
1403 else
1404 name = hostname;
1405
1406 len = strlen(name);
1407
1408 /* We'll add a space after the name to respect the log format */
1409 free(global.log_send_hostname);
1410 global.log_send_hostname = malloc(len + 2);
1411 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1412 }
Kevinm48936af2010-12-22 16:08:21 +00001413 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1414 if (*(args[1]) == 0) {
1415 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1416 err_code |= ERR_ALERT | ERR_FATAL;
1417 goto out;
1418 }
1419 free(global.log_tag);
1420 global.log_tag = strdup(args[1]);
1421 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001422 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1423 if (global.spread_checks != 0) {
1424 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001425 err_code |= ERR_ALERT;
1426 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001427 }
1428 if (*(args[1]) == 0) {
1429 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001432 }
1433 global.spread_checks = atol(args[1]);
1434 if (global.spread_checks < 0 || global.spread_checks > 50) {
1435 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001439 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1440 const char *err;
1441 unsigned int val;
1442
1443
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449
1450 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1451 if (err) {
1452 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 }
1455 global.max_spread_checks = val;
1456 if (global.max_spread_checks < 0) {
1457 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1458 err_code |= ERR_ALERT | ERR_FATAL;
1459 }
1460 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001461 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1462#ifdef USE_CPU_AFFINITY
1463 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001464 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001465 unsigned long cpus = 0;
1466
1467 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001468 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001469 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001470 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001471 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001472 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001473 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001474 proc = atol(args[1]);
1475 if (proc >= 1 && proc <= LONGBITS)
1476 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001477 }
1478
1479 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001480 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",
1481 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 cur_arg = 2;
1487 while (*args[cur_arg]) {
1488 unsigned int low, high;
1489
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001490 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001491 char *dash = strchr(args[cur_arg], '-');
1492
1493 low = high = str2uic(args[cur_arg]);
1494 if (dash)
1495 high = str2uic(dash + 1);
1496
1497 if (high < low) {
1498 unsigned int swap = low;
1499 low = high;
1500 high = swap;
1501 }
1502
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001503 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001504 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001505 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 while (low <= high)
1511 cpus |= 1UL << low++;
1512 }
1513 else {
1514 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1515 file, linenum, args[0], args[cur_arg]);
1516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
1518 }
1519 cur_arg++;
1520 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001521 for (i = 0; i < LONGBITS; i++)
1522 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001523 global.cpu_map[i] = cpus;
1524#else
1525 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1526 err_code |= ERR_ALERT | ERR_FATAL;
1527 goto out;
1528#endif
1529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001531 struct cfg_kw_list *kwl;
1532 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001533 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001534
1535 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1536 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1537 if (kwl->kw[index].section != CFG_GLOBAL)
1538 continue;
1539 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001540 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001541 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001542 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001544 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001545 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001546 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001547 err_code |= ERR_WARN;
1548 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001549 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001551 }
1552 }
1553 }
1554
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001556 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001558
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001560 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562}
1563
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001564void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001566 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 defproxy.mode = PR_MODE_TCP;
1568 defproxy.state = PR_STNEW;
1569 defproxy.maxconn = cfg_maxpconn;
1570 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001571
Simon Horman66183002013-02-23 10:16:43 +09001572 defproxy.defsrv.check.inter = DEF_CHKINTR;
1573 defproxy.defsrv.check.fastinter = 0;
1574 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001575 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1576 defproxy.defsrv.agent.fastinter = 0;
1577 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001578 defproxy.defsrv.check.rise = DEF_RISETIME;
1579 defproxy.defsrv.check.fall = DEF_FALLTIME;
1580 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1581 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001582 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001583 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001584 defproxy.defsrv.maxqueue = 0;
1585 defproxy.defsrv.minconn = 0;
1586 defproxy.defsrv.maxconn = 0;
1587 defproxy.defsrv.slowstart = 0;
1588 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1589 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1590 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591}
1592
Willy Tarreauade5ec42010-01-28 19:33:49 +01001593
Willy Tarreau63af98d2014-05-18 08:11:41 +02001594/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1595 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1596 * ERR_FATAL in case of error.
1597 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001598static int create_cond_regex_rule(const char *file, int line,
1599 struct proxy *px, int dir, int action, int flags,
1600 const char *cmd, const char *reg, const char *repl,
1601 const char **cond_start)
1602{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001603 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001604 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001605 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001606 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001607 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001608 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001609 int cs;
1610 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001611
1612 if (px == &defproxy) {
1613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001614 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001615 goto err;
1616 }
1617
1618 if (*reg == 0) {
1619 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001620 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001621 goto err;
1622 }
1623
1624 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001625 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001626
Willy Tarreau5321c422010-01-28 20:35:13 +01001627 if (cond_start &&
1628 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001629 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1630 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1631 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001632 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001633 goto err;
1634 }
1635 }
1636 else if (cond_start && **cond_start) {
1637 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1638 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001639 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001640 goto err;
1641 }
1642
Willy Tarreau63af98d2014-05-18 08:11:41 +02001643 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001644 (dir == SMP_OPT_DIR_REQ) ?
1645 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1646 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1647 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001648
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001649 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001650 if (!preg) {
1651 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001652 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001653 goto err;
1654 }
1655
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001656 cs = !(flags & REG_ICASE);
1657 cap = !(flags & REG_NOSUB);
1658 error = NULL;
1659 if (!regex_comp(reg, preg, cs, cap, &error)) {
1660 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1661 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001662 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001663 goto err;
1664 }
1665
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001666 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001667 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001668 if (repl && err) {
1669 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1670 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
1672 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001673 }
1674
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001675 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_WARN;
1677
1678 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001679
Willy Tarreau63af98d2014-05-18 08:11:41 +02001680 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001681 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682 err:
1683 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001684 free(errmsg);
1685 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001686}
1687
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001689 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001690 * Returns the error code, 0 if OK, or any combination of :
1691 * - ERR_ABORT: must abort ASAP
1692 * - ERR_FATAL: we can continue parsing but not start the service
1693 * - ERR_WARN: a warning has been emitted
1694 * - ERR_ALERT: an alert has been emitted
1695 * Only the two first ones can stop processing, the two others are just
1696 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001698int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1699{
1700 static struct peers *curpeers = NULL;
1701 struct peer *newpeer = NULL;
1702 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct bind_conf *bind_conf;
1704 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001705 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001706 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001707
1708 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001709 if (!*args[1]) {
1710 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001711 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001712 goto out;
1713 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001714
1715 err = invalid_char(args[1]);
1716 if (err) {
1717 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1718 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001719 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001720 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 }
1722
1723 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1724 /*
1725 * If there are two proxies with the same name only following
1726 * combinations are allowed:
1727 */
1728 if (strcmp(curpeers->id, args[1]) == 0) {
1729 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1730 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1731 err_code |= ERR_WARN;
1732 }
1733 }
1734
1735 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1736 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1737 err_code |= ERR_ALERT | ERR_ABORT;
1738 goto out;
1739 }
1740
1741 curpeers->next = peers;
1742 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001743 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001744 curpeers->conf.line = linenum;
1745 curpeers->last_change = now.tv_sec;
1746 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001747 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001748 }
1749 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001750 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001751 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001752 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001753
1754 if (!*args[2]) {
1755 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1756 file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
1760
1761 err = invalid_char(args[1]);
1762 if (err) {
1763 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1764 file, linenum, *err, args[1]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767 }
1768
1769 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1770 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1771 err_code |= ERR_ALERT | ERR_ABORT;
1772 goto out;
1773 }
1774
1775 /* the peers are linked backwards first */
1776 curpeers->count++;
1777 newpeer->next = curpeers->remote;
1778 curpeers->remote = newpeer;
1779 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001780 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001781 newpeer->conf.line = linenum;
1782
1783 newpeer->last_change = now.tv_sec;
1784 newpeer->id = strdup(args[1]);
1785
Willy Tarreau902636f2013-03-10 19:44:48 +01001786 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001787 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001788 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001791 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001792
1793 proto = protocol_by_family(sk->ss_family);
1794 if (!proto || !proto->connect) {
1795 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1796 file, linenum, args[0], args[1]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001800
1801 if (port1 != port2) {
1802 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1803 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001804 err_code |= ERR_ALERT | ERR_FATAL;
1805 goto out;
1806 }
1807
Willy Tarreau2aa38802013-02-20 19:20:59 +01001808 if (!port1) {
1809 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1810 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001814
Emeric Brun32da3c42010-09-23 18:39:19 +02001815 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001816 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001817 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001818 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001819
Emeric Brun32da3c42010-09-23 18:39:19 +02001820 if (strcmp(newpeer->id, localpeer) == 0) {
1821 /* Current is local peer, it define a frontend */
1822 newpeer->local = 1;
1823
1824 if (!curpeers->peers_fe) {
1825 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1826 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1827 err_code |= ERR_ALERT | ERR_ABORT;
1828 goto out;
1829 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001830
Willy Tarreau237250c2011-07-29 01:49:03 +02001831 init_new_proxy(curpeers->peers_fe);
1832 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001833
1834 curpeers->peers_fe->last_change = now.tv_sec;
1835 curpeers->peers_fe->id = strdup(args[1]);
1836 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001837 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001838 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001839 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001840 curpeers->peers_fe->accept = peer_accept;
1841 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001842 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1843 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreaucdb5e922015-05-01 19:12:05 +02001844 curpeers->peers_fe->bind_proc = 0; /* will be filled by users */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001845
1846 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1847
Willy Tarreau902636f2013-03-10 19:44:48 +01001848 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1849 if (errmsg && *errmsg) {
1850 indent_msg(&errmsg, 2);
1851 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001852 }
1853 else
1854 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1855 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001856 err_code |= ERR_FATAL;
1857 goto out;
1858 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001859
1860 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001861 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001862 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1863 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1864 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1865 l->accept = session_accept;
1866 l->handler = process_session;
1867 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1868 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1869 global.maxsock += l->maxconn;
1870 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001871 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001872 else {
1873 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1874 file, linenum, args[0], args[1],
1875 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1876 err_code |= ERR_FATAL;
1877 goto out;
1878 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001879 }
1880 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001881 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1882 curpeers->state = PR_STSTOPPED;
1883 }
1884 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1885 curpeers->state = PR_STNEW;
1886 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001887 else if (*args[0] != 0) {
1888 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
1891 }
1892
1893out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001894 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001895 return err_code;
1896}
1897
Willy Tarreau3842f002009-06-14 11:39:52 +02001898int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899{
1900 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001901 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001902 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001903 int rc;
1904 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001905 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001906 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001907 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001908 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001909 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911 if (!strcmp(args[0], "listen"))
1912 rc = PR_CAP_LISTEN;
1913 else if (!strcmp(args[0], "frontend"))
1914 rc = PR_CAP_FE | PR_CAP_RS;
1915 else if (!strcmp(args[0], "backend"))
1916 rc = PR_CAP_BE | PR_CAP_RS;
1917 else if (!strcmp(args[0], "ruleset"))
1918 rc = PR_CAP_RS;
1919 else
1920 rc = PR_CAP_NONE;
1921
1922 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001923 struct ebpt_node *node;
1924
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 if (!*args[1]) {
1926 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1927 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_ABORT;
1930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001932
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001933 err = invalid_char(args[1]);
1934 if (err) {
1935 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1936 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001938 }
1939
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001940 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1941 curproxy = container_of(node, struct proxy, conf.by_name);
1942
1943 if (strcmp(curproxy->id, args[1]) != 0)
1944 break;
1945
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001946 /*
1947 * If there are two proxies with the same name only following
1948 * combinations are allowed:
1949 *
1950 * listen backend frontend ruleset
1951 * listen - - - -
1952 * backend - - OK -
1953 * frontend - OK - -
1954 * ruleset - - - -
1955 */
1956
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001957 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1958 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001959 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1960 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1961 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001963 }
1964 }
1965
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1967 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001968 err_code |= ERR_ALERT | ERR_ABORT;
1969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001971
Willy Tarreau97cb7802010-01-03 20:23:58 +01001972 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 curproxy->next = proxy;
1974 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001975 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1976 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001977 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001980 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981
1982 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001983 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001984 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001985
Willy Tarreau4348fad2012-09-20 16:48:07 +02001986 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1987
Willy Tarreau902636f2013-03-10 19:44:48 +01001988 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1989 if (errmsg && *errmsg) {
1990 indent_msg(&errmsg, 2);
1991 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001992 }
1993 else
1994 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1995 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001996 err_code |= ERR_FATAL;
1997 goto out;
1998 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001999
Willy Tarreau4348fad2012-09-20 16:48:07 +02002000 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002001 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 }
2004
2005 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002006 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002007 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002008
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002011 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002012 curproxy->no_options = defproxy.no_options;
2013 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002014 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002015 curproxy->except_net = defproxy.except_net;
2016 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002017 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002018 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002019
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002020 if (defproxy.fwdfor_hdr_len) {
2021 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2022 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2023 }
2024
Willy Tarreaub86db342009-11-30 11:50:16 +01002025 if (defproxy.orgto_hdr_len) {
2026 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2027 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2028 }
2029
Mark Lamourinec2247f02012-01-04 13:02:01 -05002030 if (defproxy.server_id_hdr_len) {
2031 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2032 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2033 }
2034
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035 if (curproxy->cap & PR_CAP_FE) {
2036 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002037 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002038 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039
2040 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002041 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2042 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002043
2044 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002048 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049 curproxy->fullconn = defproxy.fullconn;
2050 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002051 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002053 if (defproxy.check_req) {
2054 curproxy->check_req = calloc(1, defproxy.check_len);
2055 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2056 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002058
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002059 if (defproxy.expect_str) {
2060 curproxy->expect_str = strdup(defproxy.expect_str);
2061 if (defproxy.expect_regex) {
2062 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002063 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2064 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002065 }
2066 }
2067
Willy Tarreau67402132012-05-31 20:40:20 +02002068 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002069 if (defproxy.cookie_name)
2070 curproxy->cookie_name = strdup(defproxy.cookie_name);
2071 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002072 if (defproxy.cookie_domain)
2073 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002074
Willy Tarreau31936852010-10-06 16:59:56 +02002075 if (defproxy.cookie_maxidle)
2076 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2077
2078 if (defproxy.cookie_maxlife)
2079 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2080
Emeric Brun647caf12009-06-30 17:57:00 +02002081 if (defproxy.rdp_cookie_name)
2082 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2083 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2084
Willy Tarreau01732802007-11-01 22:48:15 +01002085 if (defproxy.url_param_name)
2086 curproxy->url_param_name = strdup(defproxy.url_param_name);
2087 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002088
Benoitaffb4812009-03-25 13:02:10 +01002089 if (defproxy.hh_name)
2090 curproxy->hh_name = strdup(defproxy.hh_name);
2091 curproxy->hh_len = defproxy.hh_len;
2092 curproxy->hh_match_domain = defproxy.hh_match_domain;
2093
Willy Tarreauef9a3602012-12-08 22:29:20 +01002094 if (defproxy.conn_src.iface_name)
2095 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2096 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002097 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002098#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002099 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002100#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002103 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 if (defproxy.capture_name)
2105 curproxy->capture_name = strdup(defproxy.capture_name);
2106 curproxy->capture_namelen = defproxy.capture_namelen;
2107 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109
Willy Tarreau977b8e42006-12-29 14:19:17 +01002110 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002111 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002112 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002113 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002114 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002115 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002116 curproxy->mon_net = defproxy.mon_net;
2117 curproxy->mon_mask = defproxy.mon_mask;
2118 if (defproxy.monitor_uri)
2119 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2120 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002121 if (defproxy.defbe.name)
2122 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002123
2124 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002125 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2126 if (curproxy->conf.logformat_string &&
2127 curproxy->conf.logformat_string != default_http_log_format &&
2128 curproxy->conf.logformat_string != default_tcp_log_format &&
2129 curproxy->conf.logformat_string != clf_http_log_format)
2130 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2131
2132 if (defproxy.conf.lfs_file) {
2133 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2134 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2135 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002136 }
2137
2138 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002139 curproxy->timeout.connect = defproxy.timeout.connect;
2140 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002141 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002142 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002143 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002144 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002145 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002146 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002147 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002148 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002149 }
2150
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002152 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002153
2154 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002155 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002156 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002157 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002158 LIST_INIT(&node->list);
2159 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2160 }
2161
Willy Tarreau62a61232013-04-12 18:13:46 +02002162 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2163 if (curproxy->conf.uniqueid_format_string)
2164 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2165
2166 if (defproxy.conf.uif_file) {
2167 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2168 curproxy->conf.uif_line = defproxy.conf.uif_line;
2169 }
William Lallemanda73203e2012-03-12 12:48:57 +01002170
2171 /* copy default header unique id */
2172 if (defproxy.header_unique_id)
2173 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2174
William Lallemand82fe75c2012-10-23 10:25:10 +02002175 /* default compression options */
2176 if (defproxy.comp != NULL) {
2177 curproxy->comp = calloc(1, sizeof(struct comp));
2178 curproxy->comp->algos = defproxy.comp->algos;
2179 curproxy->comp->types = defproxy.comp->types;
2180 }
2181
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002183 curproxy->conf.used_listener_id = EB_ROOT;
2184 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002185
Willy Tarreau93893792009-07-23 13:19:11 +02002186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 }
2188 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2189 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002190 /* FIXME-20070101: we should do this too at the end of the
2191 * config parsing to free all default values.
2192 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002193 free(defproxy.check_req);
2194 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002195 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002196 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002197 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002198 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002199 free(defproxy.capture_name);
2200 free(defproxy.monitor_uri);
2201 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002202 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002203 free(defproxy.fwdfor_hdr_name);
2204 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002205 free(defproxy.orgto_hdr_name);
2206 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002207 free(defproxy.server_id_hdr_name);
2208 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002209 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002210 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002211 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002212 free(defproxy.expect_regex);
2213 defproxy.expect_regex = NULL;
2214 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002215
Willy Tarreau62a61232013-04-12 18:13:46 +02002216 if (defproxy.conf.logformat_string != default_http_log_format &&
2217 defproxy.conf.logformat_string != default_tcp_log_format &&
2218 defproxy.conf.logformat_string != clf_http_log_format)
2219 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002220
Willy Tarreau62a61232013-04-12 18:13:46 +02002221 free(defproxy.conf.uniqueid_format_string);
2222 free(defproxy.conf.lfs_file);
2223 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002224
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002226 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002227
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 /* we cannot free uri_auth because it might already be used */
2229 init_default_instance();
2230 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002231 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2232 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002233 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 }
2236 else if (curproxy == NULL) {
2237 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002241
2242 /* update the current file and line being parsed */
2243 curproxy->conf.args.file = curproxy->conf.file;
2244 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002245
2246 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002247 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2248 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2249 if (err_code & ERR_FATAL)
2250 goto out;
2251 }
2252 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002253 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002254 int cur_arg;
2255
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 if (curproxy == &defproxy) {
2257 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002261 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263
Willy Tarreau24709282013-03-10 21:32:12 +01002264 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002265 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002270
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002271 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002272
2273 /* use default settings for unix sockets */
2274 bind_conf->ux.uid = global.unix_bind.ux.uid;
2275 bind_conf->ux.gid = global.unix_bind.ux.gid;
2276 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002277
2278 /* NOTE: the following line might create several listeners if there
2279 * are comma-separated IPs or port ranges. So all further processing
2280 * will have to be applied to all listeners created after last_listen.
2281 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002282 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2283 if (errmsg && *errmsg) {
2284 indent_msg(&errmsg, 2);
2285 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002286 }
2287 else
2288 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2289 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002293
Willy Tarreau4348fad2012-09-20 16:48:07 +02002294 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2295 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002296 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002297 }
2298
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002299 cur_arg = 2;
2300 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002301 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002302 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002303 char *err;
2304
Willy Tarreau26982662012-09-12 23:17:10 +02002305 kw = bind_find_kw(args[cur_arg]);
2306 if (kw) {
2307 char *err = NULL;
2308 int code;
2309
2310 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002311 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2312 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002313 cur_arg += 1 + kw->skip ;
2314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
2316 }
2317
Willy Tarreau4348fad2012-09-20 16:48:07 +02002318 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002319 err_code |= code;
2320
2321 if (code) {
2322 if (err && *err) {
2323 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002324 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002325 }
2326 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002327 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2328 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002329 if (code & ERR_FATAL) {
2330 free(err);
2331 cur_arg += 1 + kw->skip;
2332 goto out;
2333 }
2334 }
2335 free(err);
2336 cur_arg += 1 + kw->skip;
2337 continue;
2338 }
2339
Willy Tarreau8638f482012-09-18 18:01:17 +02002340 err = NULL;
2341 if (!bind_dumped) {
2342 bind_dump_kws(&err);
2343 indent_msg(&err, 4);
2344 bind_dumped = 1;
2345 }
2346
2347 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2348 file, linenum, args[0], args[1], args[cur_arg],
2349 err ? " Registered keywords :" : "", err ? err : "");
2350 free(err);
2351
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002354 }
Willy Tarreau93893792009-07-23 13:19:11 +02002355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
2357 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002358 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2360 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002364 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002366
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 /* flush useless bits */
2368 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002371 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002372 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002374
Willy Tarreau1c47f852006-07-09 08:22:27 +02002375 if (!*args[1]) {
2376 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2377 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_ALERT | ERR_FATAL;
2379 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002380 }
2381
Willy Tarreaua534fea2008-08-03 12:19:50 +02002382 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002383 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002384 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002385 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002386 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2387
Willy Tarreau93893792009-07-23 13:19:11 +02002388 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2391 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2392 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2393 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2394 else {
2395 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
2399 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002400 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002401 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002402
2403 if (curproxy == &defproxy) {
2404 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2405 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002408 }
2409
2410 if (!*args[1]) {
2411 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2412 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002415 }
2416
2417 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002418 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002419
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002420 if (curproxy->uuid <= 0) {
2421 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002422 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002425 }
2426
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002427 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2428 if (node) {
2429 struct proxy *target = container_of(node, struct proxy, conf.id);
2430 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2431 file, linenum, proxy_type_str(curproxy), curproxy->id,
2432 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
2435 }
2436 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002437 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002438 else if (!strcmp(args[0], "description")) {
2439 int i, len=0;
2440 char *d;
2441
Cyril Bonté99ed3272010-01-24 23:29:44 +01002442 if (curproxy == &defproxy) {
2443 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2444 file, linenum, args[0]);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
2447 }
2448
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002449 if (!*args[1]) {
2450 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2451 file, linenum, args[0]);
2452 return -1;
2453 }
2454
Willy Tarreau348acfe2014-04-14 15:00:39 +02002455 for (i = 1; *args[i]; i++)
2456 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002457
2458 d = (char *)calloc(1, len);
2459 curproxy->desc = d;
2460
Willy Tarreau348acfe2014-04-14 15:00:39 +02002461 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2462 for (i = 2; *args[i]; i++)
2463 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002464
2465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2467 curproxy->state = PR_STSTOPPED;
2468 }
2469 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2470 curproxy->state = PR_STNEW;
2471 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002472 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2473 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002474 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002475
2476 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002477 unsigned int low, high;
2478
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002479 if (strcmp(args[cur_arg], "all") == 0) {
2480 set = 0;
2481 break;
2482 }
2483 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002484 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002485 }
2486 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002487 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002488 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002489 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002490 char *dash = strchr(args[cur_arg], '-');
2491
2492 low = high = str2uic(args[cur_arg]);
2493 if (dash)
2494 high = str2uic(dash + 1);
2495
2496 if (high < low) {
2497 unsigned int swap = low;
2498 low = high;
2499 high = swap;
2500 }
2501
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002502 if (low < 1 || high > LONGBITS) {
2503 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2504 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002507 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002508 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002509 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002510 }
2511 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002512 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2513 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002516 }
2517 cur_arg++;
2518 }
2519 curproxy->bind_proc = set;
2520 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002521 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002522 if (curproxy == &defproxy) {
2523 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002526 }
2527
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002528 err = invalid_char(args[1]);
2529 if (err) {
2530 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2531 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002532 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002533 }
2534
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002535 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002536 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2537 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
2539 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002540 }
2541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2543 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544
Willy Tarreau977b8e42006-12-29 14:19:17 +01002545 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 if (*(args[1]) == 0) {
2549 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002554
Willy Tarreau67402132012-05-31 20:40:20 +02002555 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002556 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002557 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002558 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 curproxy->cookie_name = strdup(args[1]);
2560 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002561
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 cur_arg = 2;
2563 while (*(args[cur_arg])) {
2564 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002565 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 }
2567 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002568 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002571 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
2573 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002574 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
2576 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002577 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002579 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002580 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002583 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002585 else if (!strcmp(args[cur_arg], "httponly")) {
2586 curproxy->ck_opts |= PR_CK_HTTPONLY;
2587 }
2588 else if (!strcmp(args[cur_arg], "secure")) {
2589 curproxy->ck_opts |= PR_CK_SECURE;
2590 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002591 else if (!strcmp(args[cur_arg], "domain")) {
2592 if (!*args[cur_arg + 1]) {
2593 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2594 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002597 }
2598
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002599 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002600 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002601 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2602 " dots nor does not start with a dot."
2603 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002604 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002605 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002606 }
2607
2608 err = invalid_domainchar(args[cur_arg + 1]);
2609 if (err) {
2610 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2611 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002614 }
2615
Willy Tarreau68a897b2009-12-03 23:28:34 +01002616 if (!curproxy->cookie_domain) {
2617 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2618 } else {
2619 /* one domain was already specified, add another one by
2620 * building the string which will be returned along with
2621 * the cookie.
2622 */
2623 char *new_ptr;
2624 int new_len = strlen(curproxy->cookie_domain) +
2625 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2626 new_ptr = malloc(new_len);
2627 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2628 free(curproxy->cookie_domain);
2629 curproxy->cookie_domain = new_ptr;
2630 }
Willy Tarreau31936852010-10-06 16:59:56 +02002631 cur_arg++;
2632 }
2633 else if (!strcmp(args[cur_arg], "maxidle")) {
2634 unsigned int maxidle;
2635 const char *res;
2636
2637 if (!*args[cur_arg + 1]) {
2638 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2639 file, linenum, args[cur_arg]);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643
2644 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2645 if (res) {
2646 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2647 file, linenum, *res, args[cur_arg]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651 curproxy->cookie_maxidle = maxidle;
2652 cur_arg++;
2653 }
2654 else if (!strcmp(args[cur_arg], "maxlife")) {
2655 unsigned int maxlife;
2656 const char *res;
2657
2658 if (!*args[cur_arg + 1]) {
2659 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2660 file, linenum, args[cur_arg]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664
2665 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2666 if (res) {
2667 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2668 file, linenum, *res, args[cur_arg]);
2669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
2671 }
2672 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002673 cur_arg++;
2674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002676 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 +02002677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 }
2681 cur_arg++;
2682 }
Willy Tarreau67402132012-05-31 20:40:20 +02002683 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2685 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002686 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 }
2688
Willy Tarreau67402132012-05-31 20:40:20 +02002689 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2691 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002694
Willy Tarreau67402132012-05-31 20:40:20 +02002695 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002696 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2697 file, linenum);
2698 err_code |= ERR_ALERT | ERR_FATAL;
2699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002701 else if (!strcmp(args[0], "persist")) { /* persist */
2702 if (*(args[1]) == 0) {
2703 Alert("parsing [%s:%d] : missing persist method.\n",
2704 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002707 }
2708
2709 if (!strncmp(args[1], "rdp-cookie", 10)) {
2710 curproxy->options2 |= PR_O2_RDPC_PRST;
2711
Emeric Brunb982a3d2010-01-04 15:45:53 +01002712 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002713 const char *beg, *end;
2714
2715 beg = args[1] + 11;
2716 end = strchr(beg, ')');
2717
2718 if (!end || end == beg) {
2719 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\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 free(curproxy->rdp_cookie_name);
2726 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2727 curproxy->rdp_cookie_len = end-beg;
2728 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002730 free(curproxy->rdp_cookie_name);
2731 curproxy->rdp_cookie_name = strdup("msts");
2732 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2733 }
2734 else { /* syntax */
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 else {
2742 Alert("parsing [%s:%d] : unknown persist method.\n",
2743 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002746 }
2747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002749 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002751 if (curproxy == &defproxy) {
2752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
2755 }
2756
Willy Tarreau977b8e42006-12-29 14:19:17 +01002757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002759
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002761 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 }
2766 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002767 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 curproxy->appsession_name = strdup(args[1]);
2769 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2770 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002771 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2772 if (err) {
2773 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2774 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002777 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002778 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002779
Willy Tarreau51041c72007-09-09 21:56:53 +02002780 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2781 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002782 err_code |= ERR_ALERT | ERR_ABORT;
2783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002785
2786 cur_arg = 6;
2787 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002788 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2789 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002790 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002791 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002792 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002793 } else if (!strcmp(args[cur_arg], "prefix")) {
2794 curproxy->options2 |= PR_O2_AS_PFX;
2795 } else if (!strcmp(args[cur_arg], "mode")) {
2796 if (!*args[cur_arg + 1]) {
2797 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2798 file, linenum, args[0], args[cur_arg]);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
2803 cur_arg++;
2804 if (!strcmp(args[cur_arg], "query-string")) {
2805 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2806 curproxy->options2 |= PR_O2_AS_M_QS;
2807 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2808 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2809 curproxy->options2 |= PR_O2_AS_M_PP;
2810 } else {
2811 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814 }
2815 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002816 cur_arg++;
2817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 } /* Url App Session */
2819 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002820 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002821 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002822
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002824 if (curproxy == &defproxy) {
2825 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
2828 }
2829
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 if (*(args[4]) == 0) {
2831 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002836 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 curproxy->capture_name = strdup(args[2]);
2838 curproxy->capture_namelen = strlen(curproxy->capture_name);
2839 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 curproxy->to_log |= LW_COOKIE;
2841 }
2842 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2843 struct cap_hdr *hdr;
2844
2845 if (curproxy == &defproxy) {
2846 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 +02002847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 }
2850
2851 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2852 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2853 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856 }
2857
2858 hdr = calloc(sizeof(struct cap_hdr), 1);
2859 hdr->next = curproxy->req_cap;
2860 hdr->name = strdup(args[3]);
2861 hdr->namelen = strlen(args[3]);
2862 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002863 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 hdr->index = curproxy->nb_req_cap++;
2865 curproxy->req_cap = hdr;
2866 curproxy->to_log |= LW_REQHDR;
2867 }
2868 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2869 struct cap_hdr *hdr;
2870
2871 if (curproxy == &defproxy) {
2872 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 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
2876
2877 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2878 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2879 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 }
2883 hdr = calloc(sizeof(struct cap_hdr), 1);
2884 hdr->next = curproxy->rsp_cap;
2885 hdr->name = strdup(args[3]);
2886 hdr->namelen = strlen(args[3]);
2887 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002888 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 hdr->index = curproxy->nb_rsp_cap++;
2890 curproxy->rsp_cap = hdr;
2891 curproxy->to_log |= LW_RSPHDR;
2892 }
2893 else {
2894 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2895 file, linenum, args[0]);
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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002903
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 if (*(args[1]) == 0) {
2905 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2906 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 }
2910 curproxy->conn_retries = atol(args[1]);
2911 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002912 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002913 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002914
2915 if (curproxy == &defproxy) {
2916 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
2920
Willy Tarreau20b0de52012-12-24 15:45:22 +01002921 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2922 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2923 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2924 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002925 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002926 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2927 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 +01002928 file, linenum, args[0]);
2929 err_code |= ERR_WARN;
2930 }
2931
Willy Tarreauff011f22011-01-06 17:51:27 +01002932 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002933
Willy Tarreauff011f22011-01-06 17:51:27 +01002934 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002935 err_code |= ERR_ALERT | ERR_ABORT;
2936 goto out;
2937 }
2938
Willy Tarreau5002f572014-04-23 01:32:02 +02002939 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002940 err_code |= warnif_cond_conflicts(rule->cond,
2941 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2942 file, linenum);
2943
Willy Tarreauff011f22011-01-06 17:51:27 +01002944 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002945 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002946 else if (!strcmp(args[0], "http-response")) { /* response access control */
2947 struct http_res_rule *rule;
2948
2949 if (curproxy == &defproxy) {
2950 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
2954
2955 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2956 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2957 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2958 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2959 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2960 file, linenum, args[0]);
2961 err_code |= ERR_WARN;
2962 }
2963
2964 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2965
2966 if (!rule) {
2967 err_code |= ERR_ALERT | ERR_ABORT;
2968 goto out;
2969 }
2970
2971 err_code |= warnif_cond_conflicts(rule->cond,
2972 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2973 file, linenum);
2974
2975 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2976 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002977 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2978 /* set the header name and length into the proxy structure */
2979 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2980 err_code |= ERR_WARN;
2981
2982 if (!*args[1]) {
2983 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2984 file, linenum, args[0]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
2989 /* set the desired header name */
2990 free(curproxy->server_id_hdr_name);
2991 curproxy->server_id_hdr_name = strdup(args[1]);
2992 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2993 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002994 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002995 struct http_req_rule *rule;
2996
Willy Tarreaub099aca2008-10-12 17:26:37 +02002997 if (curproxy == &defproxy) {
2998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003001 }
3002
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003003 /* emulate "block" using "http-request block". Since these rules are supposed to
3004 * be processed before all http-request rules, we put them into their own list
3005 * and will insert them at the end.
3006 */
3007 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3008 if (!rule) {
3009 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003010 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003011 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003012 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3013 err_code |= warnif_cond_conflicts(rule->cond,
3014 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3015 file, linenum);
3016 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003017
3018 if (!already_warned(WARN_BLOCK_DEPRECATED))
3019 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]);
3020
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003021 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003022 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003023 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003024
Cyril Bonté99ed3272010-01-24 23:29:44 +01003025 if (curproxy == &defproxy) {
3026 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
3029 }
3030
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003031 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003032 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3033 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003036 }
3037
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003038 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003039 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003040 err_code |= warnif_cond_conflicts(rule->cond,
3041 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3042 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003043 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003044 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003045 struct switching_rule *rule;
3046
Willy Tarreaub099aca2008-10-12 17:26:37 +02003047 if (curproxy == &defproxy) {
3048 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003051 }
3052
Willy Tarreau55ea7572007-06-17 19:56:27 +02003053 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003055
3056 if (*(args[1]) == 0) {
3057 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003060 }
3061
Willy Tarreauf51658d2014-04-23 01:21:56 +02003062 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3063 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3064 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3065 file, linenum, errmsg);
3066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
3068 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003069
Willy Tarreauf51658d2014-04-23 01:21:56 +02003070 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003071 }
3072
3073 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3074 rule->cond = cond;
3075 rule->be.name = strdup(args[1]);
3076 LIST_INIT(&rule->list);
3077 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3078 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003079 else if (strcmp(args[0], "use-server") == 0) {
3080 struct server_rule *rule;
3081
3082 if (curproxy == &defproxy) {
3083 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
3086 }
3087
3088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3089 err_code |= ERR_WARN;
3090
3091 if (*(args[1]) == 0) {
3092 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096
3097 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3098 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3099 file, linenum, args[0]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003104 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3105 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3106 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
3110
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003111 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003112
3113 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3114 rule->cond = cond;
3115 rule->srv.name = strdup(args[1]);
3116 LIST_INIT(&rule->list);
3117 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3118 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3119 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003120 else if ((!strcmp(args[0], "force-persist")) ||
3121 (!strcmp(args[0], "ignore-persist"))) {
3122 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003123
3124 if (curproxy == &defproxy) {
3125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128 }
3129
3130 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3131 err_code |= ERR_WARN;
3132
Willy Tarreauef6494c2010-01-28 17:12:36 +01003133 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003134 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3135 file, linenum, args[0]);
3136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
3138 }
3139
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003140 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3141 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3142 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
3145 }
3146
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003147 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3148 * where force-persist is applied.
3149 */
3150 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003151
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003152 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003153 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003154 if (!strcmp(args[0], "force-persist")) {
3155 rule->type = PERSIST_TYPE_FORCE;
3156 } else {
3157 rule->type = PERSIST_TYPE_IGNORE;
3158 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003159 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003160 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003161 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 else if (!strcmp(args[0], "stick-table")) {
3163 int myidx = 1;
3164
Emeric Brun32da3c42010-09-23 18:39:19 +02003165 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 curproxy->table.type = (unsigned int)-1;
3167 while (*args[myidx]) {
3168 const char *err;
3169
3170 if (strcmp(args[myidx], "size") == 0) {
3171 myidx++;
3172 if (!*(args[myidx])) {
3173 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3174 file, linenum, args[myidx-1]);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
3178 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3179 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3180 file, linenum, *err, args[myidx-1]);
3181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
3183 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003184 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003185 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003186 else if (strcmp(args[myidx], "peers") == 0) {
3187 myidx++;
Godbach50523162013-12-11 19:48:57 +08003188 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003189 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;
Godbach50523162013-12-11 19:48:57 +08003193 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003194 curproxy->table.peers.name = strdup(args[myidx++]);
3195 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003196 else if (strcmp(args[myidx], "expire") == 0) {
3197 myidx++;
3198 if (!*(args[myidx])) {
3199 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3200 file, linenum, args[myidx-1]);
3201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
3203 }
3204 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3205 if (err) {
3206 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3207 file, linenum, *err, args[myidx-1]);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
3210 }
3211 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003212 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003213 }
3214 else if (strcmp(args[myidx], "nopurge") == 0) {
3215 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003216 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003217 }
3218 else if (strcmp(args[myidx], "type") == 0) {
3219 myidx++;
3220 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3221 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3222 file, linenum, args[myidx]);
3223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003226 /* myidx already points to next arg */
3227 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003228 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003229 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003230 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003231
3232 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003233 nw = args[myidx];
3234 while (*nw) {
3235 /* the "store" keyword supports a comma-separated list */
3236 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003237 sa = NULL; /* store arg */
3238 while (*nw && *nw != ',') {
3239 if (*nw == '(') {
3240 *nw = 0;
3241 sa = ++nw;
3242 while (*nw != ')') {
3243 if (!*nw) {
3244 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3245 file, linenum, args[0], cw);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
3249 nw++;
3250 }
3251 *nw = '\0';
3252 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003253 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003254 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003255 if (*nw)
3256 *nw++ = '\0';
3257 type = stktable_get_data_type(cw);
3258 if (type < 0) {
3259 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3260 file, linenum, args[0], cw);
3261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
3263 }
Willy Tarreauac782882010-06-20 10:41:54 +02003264
3265 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3266 switch (err) {
3267 case PE_NONE: break;
3268 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003269 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3270 file, linenum, args[0], cw);
3271 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003272 break;
3273
3274 case PE_ARG_MISSING:
3275 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3276 file, linenum, args[0], cw);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279
3280 case PE_ARG_NOT_USED:
3281 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3282 file, linenum, args[0], cw);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285
3286 default:
3287 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3288 file, linenum, args[0], cw);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003291 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003292 }
3293 myidx++;
3294 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003295 else {
3296 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3297 file, linenum, args[myidx]);
3298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003300 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003301 }
3302
3303 if (!curproxy->table.size) {
3304 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3305 file, linenum);
3306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
3308 }
3309
3310 if (curproxy->table.type == (unsigned int)-1) {
3311 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3312 file, linenum);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316 }
3317 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003318 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003319 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003320 int myidx = 0;
3321 const char *name = NULL;
3322 int flags;
3323
3324 if (curproxy == &defproxy) {
3325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
3328 }
3329
3330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3331 err_code |= ERR_WARN;
3332 goto out;
3333 }
3334
3335 myidx++;
3336 if ((strcmp(args[myidx], "store") == 0) ||
3337 (strcmp(args[myidx], "store-request") == 0)) {
3338 myidx++;
3339 flags = STK_IS_STORE;
3340 }
3341 else if (strcmp(args[myidx], "store-response") == 0) {
3342 myidx++;
3343 flags = STK_IS_STORE | STK_ON_RSP;
3344 }
3345 else if (strcmp(args[myidx], "match") == 0) {
3346 myidx++;
3347 flags = STK_IS_MATCH;
3348 }
3349 else if (strcmp(args[myidx], "on") == 0) {
3350 myidx++;
3351 flags = STK_IS_MATCH | STK_IS_STORE;
3352 }
3353 else {
3354 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
3357 }
3358
3359 if (*(args[myidx]) == 0) {
3360 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
3363 }
3364
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003365 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003366 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003367 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003368 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
3371 }
3372
3373 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003374 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3375 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3376 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003377 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003378 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003379 goto out;
3380 }
3381 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003382 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3383 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3384 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003385 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003386 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003387 goto out;
3388 }
3389 }
3390
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003391 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003392 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003393
Emeric Brunb982a3d2010-01-04 15:45:53 +01003394 if (strcmp(args[myidx], "table") == 0) {
3395 myidx++;
3396 name = args[myidx++];
3397 }
3398
Willy Tarreauef6494c2010-01-28 17:12:36 +01003399 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003400 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3401 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3402 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003403 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003404 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003405 goto out;
3406 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003407 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003408 else if (*(args[myidx])) {
3409 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3410 file, linenum, args[0], args[myidx]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003412 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003413 goto out;
3414 }
Emeric Brun97679e72010-09-23 17:56:44 +02003415 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003416 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003417 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003418 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003419
Emeric Brunb982a3d2010-01-04 15:45:53 +01003420 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3421 rule->cond = cond;
3422 rule->expr = expr;
3423 rule->flags = flags;
3424 rule->table.name = name ? strdup(name) : NULL;
3425 LIST_INIT(&rule->list);
3426 if (flags & STK_ON_RSP)
3427 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3428 else
3429 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 else if (!strcmp(args[0], "stats")) {
3432 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3433 curproxy->uri_auth = NULL; /* we must detach from the default config */
3434
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003435 if (!*args[1]) {
3436 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003437 } else if (!strcmp(args[1], "admin")) {
3438 struct stats_admin_rule *rule;
3439
3440 if (curproxy == &defproxy) {
3441 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445
3446 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3447 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3448 err_code |= ERR_ALERT | ERR_ABORT;
3449 goto out;
3450 }
3451
3452 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3453 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3454 file, linenum, args[0], args[1]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003458 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3459 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3460 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003465 err_code |= warnif_cond_conflicts(cond,
3466 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3467 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003468
3469 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3470 rule->cond = cond;
3471 LIST_INIT(&rule->list);
3472 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 } else if (!strcmp(args[1], "uri")) {
3474 if (*(args[2]) == 0) {
3475 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003476 err_code |= ERR_ALERT | ERR_FATAL;
3477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3479 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_ALERT | ERR_ABORT;
3481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 }
3483 } else if (!strcmp(args[1], "realm")) {
3484 if (*(args[2]) == 0) {
3485 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003486 err_code |= ERR_ALERT | ERR_FATAL;
3487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003488 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3489 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_ALERT | ERR_ABORT;
3491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003493 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003494 unsigned interval;
3495
3496 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3497 if (err) {
3498 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3499 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003502 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_ABORT;
3505 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003506 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003507 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003508 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003509
3510 if (curproxy == &defproxy) {
3511 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
3514 }
3515
3516 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3517 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3518 err_code |= ERR_ALERT | ERR_ABORT;
3519 goto out;
3520 }
3521
Willy Tarreauff011f22011-01-06 17:51:27 +01003522 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3523 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003524 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3525 file, linenum, args[0]);
3526 err_code |= ERR_WARN;
3527 }
3528
Willy Tarreauff011f22011-01-06 17:51:27 +01003529 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003530
Willy Tarreauff011f22011-01-06 17:51:27 +01003531 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003532 err_code |= ERR_ALERT | ERR_ABORT;
3533 goto out;
3534 }
3535
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003536 err_code |= warnif_cond_conflicts(rule->cond,
3537 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3538 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003539 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003540
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 } else if (!strcmp(args[1], "auth")) {
3542 if (*(args[2]) == 0) {
3543 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3547 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_ALERT | ERR_ABORT;
3549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 }
3551 } else if (!strcmp(args[1], "scope")) {
3552 if (*(args[2]) == 0) {
3553 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003556 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3557 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_ABORT;
3559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 }
3561 } else if (!strcmp(args[1], "enable")) {
3562 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003567 } else if (!strcmp(args[1], "hide-version")) {
3568 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3569 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_ABORT;
3571 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003572 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003573 } else if (!strcmp(args[1], "show-legends")) {
3574 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3575 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3576 err_code |= ERR_ALERT | ERR_ABORT;
3577 goto out;
3578 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003579 } else if (!strcmp(args[1], "show-node")) {
3580
3581 if (*args[2]) {
3582 int i;
3583 char c;
3584
3585 for (i=0; args[2][i]; i++) {
3586 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003587 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3588 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003589 break;
3590 }
3591
3592 if (!i || args[2][i]) {
3593 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3594 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3595 file, linenum, args[0], args[1]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599 }
3600
3601 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3602 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3603 err_code |= ERR_ALERT | ERR_ABORT;
3604 goto out;
3605 }
3606 } else if (!strcmp(args[1], "show-desc")) {
3607 char *desc = NULL;
3608
3609 if (*args[2]) {
3610 int i, len=0;
3611 char *d;
3612
Willy Tarreau348acfe2014-04-14 15:00:39 +02003613 for (i = 2; *args[i]; i++)
3614 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003615
3616 desc = d = (char *)calloc(1, len);
3617
Willy Tarreau348acfe2014-04-14 15:00:39 +02003618 d += snprintf(d, desc + len - d, "%s", args[2]);
3619 for (i = 3; *args[i]; i++)
3620 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003621 }
3622
3623 if (!*args[2] && !global.desc)
3624 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3625 file, linenum, args[1]);
3626 else {
3627 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3628 free(desc);
3629 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3630 err_code |= ERR_ALERT | ERR_ABORT;
3631 goto out;
3632 }
3633 free(desc);
3634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003636stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003637 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 +01003638 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 }
3642 }
3643 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003644 int optnum;
3645
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003646 if (*(args[1]) == '\0') {
3647 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3648 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003652
3653 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3654 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003655 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3656 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3657 file, linenum, cfg_opts[optnum].name);
3658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
3660 }
Willy Tarreau93893792009-07-23 13:19:11 +02003661 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3662 err_code |= ERR_WARN;
3663 goto out;
3664 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003665
Willy Tarreau3842f002009-06-14 11:39:52 +02003666 curproxy->no_options &= ~cfg_opts[optnum].val;
3667 curproxy->options &= ~cfg_opts[optnum].val;
3668
3669 switch (kwm) {
3670 case KWM_STD:
3671 curproxy->options |= cfg_opts[optnum].val;
3672 break;
3673 case KWM_NO:
3674 curproxy->no_options |= cfg_opts[optnum].val;
3675 break;
3676 case KWM_DEF: /* already cleared */
3677 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003678 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003679
Willy Tarreau93893792009-07-23 13:19:11 +02003680 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003681 }
3682 }
3683
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003684 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3685 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003686 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3687 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3688 file, linenum, cfg_opts2[optnum].name);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
Willy Tarreau93893792009-07-23 13:19:11 +02003692 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3693 err_code |= ERR_WARN;
3694 goto out;
3695 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003696
Willy Tarreau3842f002009-06-14 11:39:52 +02003697 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3698 curproxy->options2 &= ~cfg_opts2[optnum].val;
3699
3700 switch (kwm) {
3701 case KWM_STD:
3702 curproxy->options2 |= cfg_opts2[optnum].val;
3703 break;
3704 case KWM_NO:
3705 curproxy->no_options2 |= cfg_opts2[optnum].val;
3706 break;
3707 case KWM_DEF: /* already cleared */
3708 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003709 }
Willy Tarreau93893792009-07-23 13:19:11 +02003710 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003711 }
3712 }
3713
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003714 /* HTTP options override each other. They can be cancelled using
3715 * "no option xxx" which only switches to default mode if the mode
3716 * was this one (useful for cancelling options set in defaults
3717 * sections).
3718 */
3719 if (strcmp(args[1], "httpclose") == 0) {
3720 if (kwm == KWM_STD) {
3721 curproxy->options &= ~PR_O_HTTP_MODE;
3722 curproxy->options |= PR_O_HTTP_PCL;
3723 goto out;
3724 }
3725 else if (kwm == KWM_NO) {
3726 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3727 curproxy->options &= ~PR_O_HTTP_MODE;
3728 goto out;
3729 }
3730 }
3731 else if (strcmp(args[1], "forceclose") == 0) {
3732 if (kwm == KWM_STD) {
3733 curproxy->options &= ~PR_O_HTTP_MODE;
3734 curproxy->options |= PR_O_HTTP_FCL;
3735 goto out;
3736 }
3737 else if (kwm == KWM_NO) {
3738 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3739 curproxy->options &= ~PR_O_HTTP_MODE;
3740 goto out;
3741 }
3742 }
3743 else if (strcmp(args[1], "http-server-close") == 0) {
3744 if (kwm == KWM_STD) {
3745 curproxy->options &= ~PR_O_HTTP_MODE;
3746 curproxy->options |= PR_O_HTTP_SCL;
3747 goto out;
3748 }
3749 else if (kwm == KWM_NO) {
3750 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3751 curproxy->options &= ~PR_O_HTTP_MODE;
3752 goto out;
3753 }
3754 }
3755 else if (strcmp(args[1], "http-keep-alive") == 0) {
3756 if (kwm == KWM_STD) {
3757 curproxy->options &= ~PR_O_HTTP_MODE;
3758 curproxy->options |= PR_O_HTTP_KAL;
3759 goto out;
3760 }
3761 else if (kwm == KWM_NO) {
3762 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3763 curproxy->options &= ~PR_O_HTTP_MODE;
3764 goto out;
3765 }
3766 }
3767 else if (strcmp(args[1], "http-tunnel") == 0) {
3768 if (kwm == KWM_STD) {
3769 curproxy->options &= ~PR_O_HTTP_MODE;
3770 curproxy->options |= PR_O_HTTP_TUN;
3771 goto out;
3772 }
3773 else if (kwm == KWM_NO) {
3774 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3775 curproxy->options &= ~PR_O_HTTP_MODE;
3776 goto out;
3777 }
3778 }
3779
Willy Tarreau3842f002009-06-14 11:39:52 +02003780 if (kwm != KWM_STD) {
3781 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003782 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003785 }
3786
Emeric Brun3a058f32009-06-30 18:26:00 +02003787 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003788 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003790 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003791 if (*(args[2]) != '\0') {
3792 if (!strcmp(args[2], "clf")) {
3793 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003794 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003795 } else {
William Lallemand629b1c02015-05-28 18:02:48 +02003796 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003799 }
3800 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003801 if (curproxy->conf.logformat_string != default_http_log_format &&
3802 curproxy->conf.logformat_string != default_tcp_log_format &&
3803 curproxy->conf.logformat_string != clf_http_log_format)
3804 free(curproxy->conf.logformat_string);
3805 curproxy->conf.logformat_string = logformat;
3806
3807 free(curproxy->conf.lfs_file);
3808 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3809 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003810 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003811 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003813 if (curproxy->conf.logformat_string != default_http_log_format &&
3814 curproxy->conf.logformat_string != default_tcp_log_format &&
3815 curproxy->conf.logformat_string != clf_http_log_format)
3816 free(curproxy->conf.logformat_string);
3817 curproxy->conf.logformat_string = default_tcp_log_format;
3818
3819 free(curproxy->conf.lfs_file);
3820 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3821 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 else if (!strcmp(args[1], "tcpka")) {
3824 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003825 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003827
3828 if (curproxy->cap & PR_CAP_FE)
3829 curproxy->options |= PR_O_TCP_CLI_KA;
3830 if (curproxy->cap & PR_CAP_BE)
3831 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 }
3833 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_WARN;
3836
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003838 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003839 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003840 curproxy->options2 &= ~PR_O2_CHK_ANY;
3841 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 if (!*args[2]) { /* no argument */
3843 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3844 curproxy->check_len = strlen(DEF_CHECK_REQ);
3845 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003846 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 curproxy->check_req = (char *)malloc(reqlen);
3848 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003849 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003851 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 if (*args[4])
3853 reqlen += strlen(args[4]);
3854 else
3855 reqlen += strlen("HTTP/1.0");
3856
3857 curproxy->check_req = (char *)malloc(reqlen);
3858 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003859 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003861 }
3862 else if (!strcmp(args[1], "ssl-hello-chk")) {
3863 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003866
Willy Tarreaua534fea2008-08-03 12:19:50 +02003867 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003868 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003869 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003870 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 }
Willy Tarreau23677902007-05-08 23:50:35 +02003872 else if (!strcmp(args[1], "smtpchk")) {
3873 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003874 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003875 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003876 curproxy->options2 &= ~PR_O2_CHK_ANY;
3877 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003878
3879 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3880 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3881 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3882 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3883 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3884 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3885 curproxy->check_req = (char *)malloc(reqlen);
3886 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3887 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3888 } else {
3889 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3890 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3891 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3892 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3893 }
3894 }
3895 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003896 else if (!strcmp(args[1], "pgsql-check")) {
3897 /* use PostgreSQL request to check servers' health */
3898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3899 err_code |= ERR_WARN;
3900
3901 free(curproxy->check_req);
3902 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003903 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003904 curproxy->options2 |= PR_O2_PGSQL_CHK;
3905
3906 if (*(args[2])) {
3907 int cur_arg = 2;
3908
3909 while (*(args[cur_arg])) {
3910 if (strcmp(args[cur_arg], "user") == 0) {
3911 char * packet;
3912 uint32_t packet_len;
3913 uint32_t pv;
3914
3915 /* suboption header - needs additional argument for it */
3916 if (*(args[cur_arg+1]) == 0) {
3917 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3918 file, linenum, args[0], args[1], args[cur_arg]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922
3923 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3924 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3925 pv = htonl(0x30000); /* protocol version 3.0 */
3926
3927 packet = (char*) calloc(1, packet_len);
3928
3929 memcpy(packet + 4, &pv, 4);
3930
3931 /* copy "user" */
3932 memcpy(packet + 8, "user", 4);
3933
3934 /* copy username */
3935 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3936
3937 free(curproxy->check_req);
3938 curproxy->check_req = packet;
3939 curproxy->check_len = packet_len;
3940
3941 packet_len = htonl(packet_len);
3942 memcpy(packet, &packet_len, 4);
3943 cur_arg += 2;
3944 } else {
3945 /* unknown suboption - catchall */
3946 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3947 file, linenum, args[0], args[1]);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
3951 } /* end while loop */
3952 }
3953 }
3954
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003955 else if (!strcmp(args[1], "redis-check")) {
3956 /* use REDIS PING request to check servers' health */
3957 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3958 err_code |= ERR_WARN;
3959
3960 free(curproxy->check_req);
3961 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003962 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003963 curproxy->options2 |= PR_O2_REDIS_CHK;
3964
3965 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3966 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3967 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3968 }
3969
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003970 else if (!strcmp(args[1], "mysql-check")) {
3971 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003972 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3973 err_code |= ERR_WARN;
3974
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003975 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003976 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003977 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003978 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003979
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003980 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003981 * const char mysql40_client_auth_pkt[] = {
3982 * "\x0e\x00\x00" // packet length
3983 * "\x01" // packet number
3984 * "\x00\x00" // client capabilities
3985 * "\x00\x00\x01" // max packet
3986 * "haproxy\x00" // username (null terminated string)
3987 * "\x00" // filler (always 0x00)
3988 * "\x01\x00\x00" // packet length
3989 * "\x00" // packet number
3990 * "\x01" // COM_QUIT command
3991 * };
3992 */
3993
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003994 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3995 * const char mysql41_client_auth_pkt[] = {
3996 * "\x0e\x00\x00\" // packet length
3997 * "\x01" // packet number
3998 * "\x00\x00\x00\x00" // client capabilities
3999 * "\x00\x00\x00\x01" // max packet
4000 * "\x21" // character set (UTF-8)
4001 * char[23] // All zeroes
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
4010
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004011 if (*(args[2])) {
4012 int cur_arg = 2;
4013
4014 while (*(args[cur_arg])) {
4015 if (strcmp(args[cur_arg], "user") == 0) {
4016 char *mysqluser;
4017 int packetlen, reqlen, userlen;
4018
4019 /* suboption header - needs additional argument for it */
4020 if (*(args[cur_arg+1]) == 0) {
4021 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4022 file, linenum, args[0], args[1], args[cur_arg]);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025 }
4026 mysqluser = args[cur_arg + 1];
4027 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004028
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004029 if (*(args[cur_arg+2])) {
4030 if (!strcmp(args[cur_arg+2], "post-41")) {
4031 packetlen = userlen + 7 + 27;
4032 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004033
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004034 free(curproxy->check_req);
4035 curproxy->check_req = (char *)calloc(1, reqlen);
4036 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004037
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004038 snprintf(curproxy->check_req, 4, "%c%c%c",
4039 ((unsigned char) packetlen & 0xff),
4040 ((unsigned char) (packetlen >> 8) & 0xff),
4041 ((unsigned char) (packetlen >> 16) & 0xff));
4042
4043 curproxy->check_req[3] = 1;
4044 curproxy->check_req[5] = 130;
4045 curproxy->check_req[11] = 1;
4046 curproxy->check_req[12] = 33;
4047 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4048 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4049 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4050 cur_arg += 3;
4051 } else {
4052 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
4055 }
4056 } else {
4057 packetlen = userlen + 7;
4058 reqlen = packetlen + 9;
4059
4060 free(curproxy->check_req);
4061 curproxy->check_req = (char *)calloc(1, reqlen);
4062 curproxy->check_len = reqlen;
4063
4064 snprintf(curproxy->check_req, 4, "%c%c%c",
4065 ((unsigned char) packetlen & 0xff),
4066 ((unsigned char) (packetlen >> 8) & 0xff),
4067 ((unsigned char) (packetlen >> 16) & 0xff));
4068
4069 curproxy->check_req[3] = 1;
4070 curproxy->check_req[5] = 128;
4071 curproxy->check_req[8] = 1;
4072 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4073 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4074 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4075 cur_arg += 2;
4076 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004077 } else {
4078 /* unknown suboption - catchall */
4079 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4080 file, linenum, args[0], args[1]);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084 } /* end while loop */
4085 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004086 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004087 else if (!strcmp(args[1], "ldap-check")) {
4088 /* use LDAP request to check servers' health */
4089 free(curproxy->check_req);
4090 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004091 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004092 curproxy->options2 |= PR_O2_LDAP_CHK;
4093
4094 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4095 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4096 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4097 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004098 else if (!strcmp(args[1], "tcp-check")) {
4099 /* use raw TCPCHK send/expect to check servers' health */
4100 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4101 err_code |= ERR_WARN;
4102
4103 free(curproxy->check_req);
4104 curproxy->check_req = NULL;
4105 curproxy->options2 &= ~PR_O2_CHK_ANY;
4106 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4107 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004108 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004109 int cur_arg;
4110
4111 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4112 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004113 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004114
Willy Tarreau87cf5142011-08-19 22:57:24 +02004115 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004116
4117 free(curproxy->fwdfor_hdr_name);
4118 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4119 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4120
4121 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4122 cur_arg = 2;
4123 while (*(args[cur_arg])) {
4124 if (!strcmp(args[cur_arg], "except")) {
4125 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004126 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004127 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4128 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004131 }
4132 /* flush useless bits */
4133 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004134 cur_arg += 2;
4135 } else if (!strcmp(args[cur_arg], "header")) {
4136 /* suboption header - needs additional argument for it */
4137 if (*(args[cur_arg+1]) == 0) {
4138 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4139 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004142 }
4143 free(curproxy->fwdfor_hdr_name);
4144 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4145 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4146 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004147 } else if (!strcmp(args[cur_arg], "if-none")) {
4148 curproxy->options &= ~PR_O_FF_ALWAYS;
4149 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004150 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004151 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004152 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004153 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004156 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004157 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004158 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004159 else if (!strcmp(args[1], "originalto")) {
4160 int cur_arg;
4161
4162 /* insert x-original-to field, but not for the IP address listed as an except.
4163 * set default options (ie: bitfield, header name, etc)
4164 */
4165
4166 curproxy->options |= PR_O_ORGTO;
4167
4168 free(curproxy->orgto_hdr_name);
4169 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4170 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4171
Willy Tarreau87cf5142011-08-19 22:57:24 +02004172 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004173 cur_arg = 2;
4174 while (*(args[cur_arg])) {
4175 if (!strcmp(args[cur_arg], "except")) {
4176 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004177 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 +02004178 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4179 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004182 }
4183 /* flush useless bits */
4184 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4185 cur_arg += 2;
4186 } else if (!strcmp(args[cur_arg], "header")) {
4187 /* suboption header - needs additional argument for it */
4188 if (*(args[cur_arg+1]) == 0) {
4189 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4190 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004193 }
4194 free(curproxy->orgto_hdr_name);
4195 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4196 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4197 cur_arg += 2;
4198 } else {
4199 /* unknown suboption - catchall */
4200 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4201 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004204 }
4205 } /* end while loop */
4206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004207 else {
4208 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 }
Willy Tarreau93893792009-07-23 13:19:11 +02004212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004213 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004214 else if (!strcmp(args[0], "default_backend")) {
4215 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004217
4218 if (*(args[1]) == 0) {
4219 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004222 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004223 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004224 curproxy->defbe.name = strdup(args[1]);
4225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004227 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004229
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004230 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4231 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 +01004232 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 /* enable reconnections to dispatch */
4235 curproxy->options |= PR_O_REDISP;
4236 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004237 else if (!strcmp(args[0], "http-check")) {
4238 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004240
4241 if (strcmp(args[1], "disable-on-404") == 0) {
4242 /* enable a graceful server shutdown on an HTTP 404 response */
4243 curproxy->options |= PR_O_DISABLE404;
4244 }
Willy Tarreauef781042010-01-27 11:53:01 +01004245 else if (strcmp(args[1], "send-state") == 0) {
4246 /* enable emission of the apparent state of a server in HTTP checks */
4247 curproxy->options2 |= PR_O2_CHK_SNDST;
4248 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004249 else if (strcmp(args[1], "expect") == 0) {
4250 const char *ptr_arg;
4251 int cur_arg;
4252
4253 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4254 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
4259 cur_arg = 2;
4260 /* consider exclamation marks, sole or at the beginning of a word */
4261 while (*(ptr_arg = args[cur_arg])) {
4262 while (*ptr_arg == '!') {
4263 curproxy->options2 ^= PR_O2_EXP_INV;
4264 ptr_arg++;
4265 }
4266 if (*ptr_arg)
4267 break;
4268 cur_arg++;
4269 }
4270 /* now ptr_arg points to the beginning of a word past any possible
4271 * exclamation mark, and cur_arg is the argument which holds this word.
4272 */
4273 if (strcmp(ptr_arg, "status") == 0) {
4274 if (!*(args[cur_arg + 1])) {
4275 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4276 file, linenum, args[0], args[1], ptr_arg);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
4280 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004281 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004282 curproxy->expect_str = strdup(args[cur_arg + 1]);
4283 }
4284 else if (strcmp(ptr_arg, "string") == 0) {
4285 if (!*(args[cur_arg + 1])) {
4286 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4287 file, linenum, args[0], args[1], ptr_arg);
4288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
4291 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004292 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004293 curproxy->expect_str = strdup(args[cur_arg + 1]);
4294 }
4295 else if (strcmp(ptr_arg, "rstatus") == 0) {
4296 if (!*(args[cur_arg + 1])) {
4297 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4298 file, linenum, args[0], args[1], ptr_arg);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004303 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004304 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004305 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004306 free(curproxy->expect_regex);
4307 curproxy->expect_regex = NULL;
4308 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004309 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004310 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4311 error = NULL;
4312 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4313 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4314 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4315 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319 }
4320 else if (strcmp(ptr_arg, "rstring") == 0) {
4321 if (!*(args[cur_arg + 1])) {
4322 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4323 file, linenum, args[0], args[1], ptr_arg);
4324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
4326 }
4327 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004328 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004329 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004330 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004331 free(curproxy->expect_regex);
4332 curproxy->expect_regex = NULL;
4333 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004334 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004335 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4336 error = NULL;
4337 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4338 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4339 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4340 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
4344 }
4345 else {
4346 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4347 file, linenum, args[0], args[1], ptr_arg);
4348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
4350 }
4351 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004352 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004353 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 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004356 }
4357 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004358 else if (!strcmp(args[0], "tcp-check")) {
4359 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4360 err_code |= ERR_WARN;
4361
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004362 if (strcmp(args[1], "connect") == 0) {
4363 const char *ptr_arg;
4364 int cur_arg;
4365 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004366
4367 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004368 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004369
Willy Tarreau5bff0592015-05-13 12:24:53 +02004370 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4371 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4372 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4373 file, linenum);
4374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004376 }
4377
4378 cur_arg = 2;
4379 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4380 tcpcheck->action = TCPCHK_ACT_CONNECT;
4381
4382 /* parsing each parameters to fill up the rule */
4383 while (*(ptr_arg = args[cur_arg])) {
4384 /* tcp port */
4385 if (strcmp(args[cur_arg], "port") == 0) {
4386 if ( (atol(args[cur_arg + 1]) > 65535) ||
4387 (atol(args[cur_arg + 1]) < 1) ){
4388 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4389 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393 tcpcheck->port = atol(args[cur_arg + 1]);
4394 cur_arg += 2;
4395 }
4396 /* send proxy protocol */
4397 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4398 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4399 cur_arg++;
4400 }
4401#ifdef USE_OPENSSL
4402 else if (strcmp(args[cur_arg], "ssl") == 0) {
4403 curproxy->options |= PR_O_TCPCHK_SSL;
4404 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4405 cur_arg++;
4406 }
4407#endif /* USE_OPENSSL */
4408 else {
4409#ifdef USE_OPENSSL
4410 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4411#else /* USE_OPENSSL */
4412 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4413#endif /* USE_OPENSSL */
4414 file, linenum, args[0], args[1], args[cur_arg]);
4415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418
4419 }
4420
4421 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4422 }
4423 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004424 if (! *(args[2]) ) {
4425 /* SEND string expected */
4426 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4427 file, linenum, args[0], args[1], args[2]);
4428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
4430 } else {
4431 struct tcpcheck_rule *tcpcheck;
4432
4433 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4434
4435 tcpcheck->action = TCPCHK_ACT_SEND;
4436 tcpcheck->string_len = strlen(args[2]);
4437 tcpcheck->string = strdup(args[2]);
4438 tcpcheck->expect_regex = NULL;
4439
4440 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4441 }
4442 }
4443 else if (strcmp(args[1], "send-binary") == 0) {
4444 if (! *(args[2]) ) {
4445 /* SEND binary string expected */
4446 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4447 file, linenum, args[0], args[1], args[2]);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 } else {
4451 struct tcpcheck_rule *tcpcheck;
4452 char *err = NULL;
4453
4454 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4455
4456 tcpcheck->action = TCPCHK_ACT_SEND;
4457 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4458 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4459 file, linenum, args[0], args[1], args[2], err);
4460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
4462 }
4463 tcpcheck->expect_regex = NULL;
4464
4465 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4466 }
4467 }
4468 else if (strcmp(args[1], "expect") == 0) {
4469 const char *ptr_arg;
4470 int cur_arg;
4471 int inverse = 0;
4472
4473 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4474 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
4477 }
4478
4479 cur_arg = 2;
4480 /* consider exclamation marks, sole or at the beginning of a word */
4481 while (*(ptr_arg = args[cur_arg])) {
4482 while (*ptr_arg == '!') {
4483 inverse = !inverse;
4484 ptr_arg++;
4485 }
4486 if (*ptr_arg)
4487 break;
4488 cur_arg++;
4489 }
4490 /* now ptr_arg points to the beginning of a word past any possible
4491 * exclamation mark, and cur_arg is the argument which holds this word.
4492 */
4493 if (strcmp(ptr_arg, "binary") == 0) {
4494 if (!*(args[cur_arg + 1])) {
4495 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4496 file, linenum, args[0], args[1], ptr_arg);
4497 err_code |= ERR_ALERT | ERR_FATAL;
4498 goto out;
4499 }
4500 struct tcpcheck_rule *tcpcheck;
4501 char *err = NULL;
4502
4503 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4504
4505 tcpcheck->action = TCPCHK_ACT_EXPECT;
4506 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4507 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4508 file, linenum, args[0], args[1], args[2], err);
4509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
4511 }
4512 tcpcheck->expect_regex = NULL;
4513 tcpcheck->inverse = inverse;
4514
4515 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4516 }
4517 else if (strcmp(ptr_arg, "string") == 0) {
4518 if (!*(args[cur_arg + 1])) {
4519 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4520 file, linenum, args[0], args[1], ptr_arg);
4521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
4523 }
4524 struct tcpcheck_rule *tcpcheck;
4525
4526 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4527
4528 tcpcheck->action = TCPCHK_ACT_EXPECT;
4529 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4530 tcpcheck->string = strdup(args[cur_arg + 1]);
4531 tcpcheck->expect_regex = NULL;
4532 tcpcheck->inverse = inverse;
4533
4534 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4535 }
4536 else if (strcmp(ptr_arg, "rstring") == 0) {
4537 if (!*(args[cur_arg + 1])) {
4538 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4539 file, linenum, args[0], args[1], ptr_arg);
4540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
4542 }
4543 struct tcpcheck_rule *tcpcheck;
4544
4545 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4546
4547 tcpcheck->action = TCPCHK_ACT_EXPECT;
4548 tcpcheck->string_len = 0;
4549 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004550 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4551 error = NULL;
4552 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4553 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4554 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4555 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
4558 }
4559 tcpcheck->inverse = inverse;
4560
4561 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4562 }
4563 else {
4564 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4565 file, linenum, args[0], args[1], ptr_arg);
4566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
4569 }
4570 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004571 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
4574 }
4575 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004576 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004577 if (curproxy == &defproxy) {
4578 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004581 }
4582
Willy Tarreaub80c2302007-11-30 20:51:32 +01004583 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004585
4586 if (strcmp(args[1], "fail") == 0) {
4587 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004588 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004589 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4590 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004593 }
4594
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004595 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4596 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4597 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004600 }
4601 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4602 }
4603 else {
4604 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004607 }
4608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609#ifdef TPROXY
4610 else if (!strcmp(args[0], "transparent")) {
4611 /* enable transparent proxy connections */
4612 curproxy->options |= PR_O_TRANSP;
4613 }
4614#endif
4615 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004616 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004617 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004618
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 if (*(args[1]) == 0) {
4620 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 }
4624 curproxy->maxconn = atol(args[1]);
4625 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004626 else if (!strcmp(args[0], "backlog")) { /* backlog */
4627 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004629
4630 if (*(args[1]) == 0) {
4631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004634 }
4635 curproxy->backlog = atol(args[1]);
4636 }
Willy Tarreau86034312006-12-29 00:10:33 +01004637 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004640
Willy Tarreau86034312006-12-29 00:10:33 +01004641 if (*(args[1]) == 0) {
4642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004645 }
4646 curproxy->fullconn = atol(args[1]);
4647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4649 if (*(args[1]) == 0) {
4650 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004653 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004654 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4655 if (err) {
4656 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4657 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004658 err_code |= ERR_ALERT | ERR_FATAL;
4659 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004660 }
4661 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 }
4663 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004664 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004665 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004666 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004667
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 if (curproxy == &defproxy) {
4669 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004670 err_code |= ERR_ALERT | ERR_FATAL;
4671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004673 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004675
Willy Tarreau902636f2013-03-10 19:44:48 +01004676 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004677 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004678 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004679 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004680 goto out;
4681 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004682
4683 proto = protocol_by_family(sk->ss_family);
4684 if (!proto || !proto->connect) {
4685 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4686 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004687 err_code |= ERR_ALERT | ERR_FATAL;
4688 goto out;
4689 }
4690
4691 if (port1 != port2) {
4692 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4693 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004697
4698 if (!port1) {
4699 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4700 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
4703 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004704
Willy Tarreaud5191e72010-02-09 20:50:45 +01004705 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004706 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
4708 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004710 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004711
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004712 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4713 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004718 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004719 /**
4720 * The syntax for hash-type config element is
4721 * hash-type {map-based|consistent} [[<algo>] avalanche]
4722 *
4723 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4724 */
4725 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004726
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004727 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4728 err_code |= ERR_WARN;
4729
4730 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004731 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4732 }
4733 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004734 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4735 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004736 else if (strcmp(args[1], "avalanche") == 0) {
4737 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]);
4738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004740 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004741 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004742 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
4745 }
Bhaskar98634f02013-10-29 23:30:51 -04004746
4747 /* set the hash function to use */
4748 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004749 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004750 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004751
4752 /* if consistent with no argument, then avalanche modifier is also applied */
4753 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4754 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004755 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004756 /* set the hash function */
4757 if (!strcmp(args[2], "sdbm")) {
4758 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4759 }
4760 else if (!strcmp(args[2], "djb2")) {
4761 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004762 } else if (!strcmp(args[2], "wt6")) {
4763 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004764 }
4765 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004766 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 -05004767 err_code |= ERR_ALERT | ERR_FATAL;
4768 goto out;
4769 }
4770
4771 /* set the hash modifier */
4772 if (!strcmp(args[3], "avalanche")) {
4773 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4774 }
4775 else if (*args[3]) {
4776 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004780 }
William Lallemanda73203e2012-03-12 12:48:57 +01004781 }
William Lallemanda73203e2012-03-12 12:48:57 +01004782 else if (strcmp(args[0], "unique-id-format") == 0) {
4783 if (!*(args[1])) {
4784 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
4787 }
William Lallemand3203ff42012-11-11 17:30:56 +01004788 if (*(args[2])) {
4789 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
4792 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004793 free(curproxy->conf.uniqueid_format_string);
4794 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004795
Willy Tarreau62a61232013-04-12 18:13:46 +02004796 free(curproxy->conf.uif_file);
4797 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4798 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004799 }
William Lallemanda73203e2012-03-12 12:48:57 +01004800
4801 else if (strcmp(args[0], "unique-id-header") == 0) {
4802 if (!*(args[1])) {
4803 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4804 err_code |= ERR_ALERT | ERR_FATAL;
4805 goto out;
4806 }
4807 free(curproxy->header_unique_id);
4808 curproxy->header_unique_id = strdup(args[1]);
4809 }
4810
William Lallemand723b73a2012-02-08 16:37:49 +01004811 else if (strcmp(args[0], "log-format") == 0) {
4812 if (!*(args[1])) {
4813 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
William Lallemand3203ff42012-11-11 17:30:56 +01004817 if (*(args[2])) {
4818 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
4821 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004822
Willy Tarreau62a61232013-04-12 18:13:46 +02004823 if (curproxy->conf.logformat_string != default_http_log_format &&
4824 curproxy->conf.logformat_string != default_tcp_log_format &&
4825 curproxy->conf.logformat_string != clf_http_log_format)
4826 free(curproxy->conf.logformat_string);
4827 curproxy->conf.logformat_string = strdup(args[1]);
4828
4829 free(curproxy->conf.lfs_file);
4830 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4831 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004832
4833 /* get a chance to improve log-format error reporting by
4834 * reporting the correct line-number when possible.
4835 */
4836 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4837 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4838 file, linenum, curproxy->id);
4839 err_code |= ERR_WARN;
4840 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 }
William Lallemand723b73a2012-02-08 16:37:49 +01004842
William Lallemand0f99e342011-10-12 17:50:54 +02004843 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4844 /* delete previous herited or defined syslog servers */
4845 struct logsrv *back;
4846
4847 if (*(args[1]) != 0) {
4848 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
4852
William Lallemand723b73a2012-02-08 16:37:49 +01004853 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4854 LIST_DEL(&tmplogsrv->list);
4855 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004856 }
4857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004859 struct logsrv *logsrv;
4860
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004862 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004863 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004864 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004865 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004866 LIST_INIT(&node->list);
4867 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
4870 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004871 struct sockaddr_storage *sk;
4872 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004873 int arg = 0;
4874 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004875
4876 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004878 /* just after the address, a length may be specified */
4879 if (strcmp(args[arg+2], "len") == 0) {
4880 len = atoi(args[arg+3]);
4881 if (len < 80 || len > 65535) {
4882 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4883 file, linenum, args[arg+3]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887 logsrv->maxlen = len;
4888
4889 /* skip these two args */
4890 arg += 2;
4891 }
4892 else
4893 logsrv->maxlen = MAX_SYSLOG_LEN;
4894
4895 if (logsrv->maxlen > global.max_syslog_len) {
4896 global.max_syslog_len = logsrv->maxlen;
4897 logline = realloc(logline, global.max_syslog_len + 1);
4898 }
4899
4900 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004901 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004902 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004903 err_code |= ERR_ALERT | ERR_FATAL;
4904 goto out;
4905
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
4907
William Lallemand0f99e342011-10-12 17:50:54 +02004908 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004909 if (*(args[arg+3])) {
4910 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004911 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004912 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
4915
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 }
4918
William Lallemand0f99e342011-10-12 17:50:54 +02004919 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004920 if (*(args[arg+4])) {
4921 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004922 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004923 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
4926
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004927 }
4928 }
4929
Willy Tarreau902636f2013-03-10 19:44:48 +01004930 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004931 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004932 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004933 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004934 goto out;
4935 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004936
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004937 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004938
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004939 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004940 if (port1 != port2) {
4941 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4942 file, linenum, args[0], args[1]);
4943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
4946
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004947 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004948 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
William Lallemand0f99e342011-10-12 17:50:54 +02004950
4951 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 else {
4954 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4955 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
4959 }
4960 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004961 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004962 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004963 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004964 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004965
Willy Tarreau977b8e42006-12-29 14:19:17 +01004966 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004968
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004970 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4971 file, linenum, "source", "usesrc", "interface");
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 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004975
4976 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004977 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4978 free(curproxy->conn_src.iface_name);
4979 curproxy->conn_src.iface_name = NULL;
4980 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004981
Willy Tarreau902636f2013-03-10 19:44:48 +01004982 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004983 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004984 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004985 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004986 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004987 goto out;
4988 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004989
4990 proto = protocol_by_family(sk->ss_family);
4991 if (!proto || !proto->connect) {
4992 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004993 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004997
4998 if (port1 != port2) {
4999 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5000 file, linenum, args[0], args[1]);
5001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003 }
5004
Willy Tarreauef9a3602012-12-08 22:29:20 +01005005 curproxy->conn_src.source_addr = *sk;
5006 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005007
5008 cur_arg = 2;
5009 while (*(args[cur_arg])) {
5010 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005011#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5012#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005013 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005014 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5015 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005018 }
5019#endif
5020 if (!*args[cur_arg + 1]) {
5021 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5022 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005025 }
5026
5027 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005028 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5029 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005030 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005031 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5032 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005033 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5034 char *name, *end;
5035
5036 name = args[cur_arg+1] + 7;
5037 while (isspace(*name))
5038 name++;
5039
5040 end = name;
5041 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5042 end++;
5043
Willy Tarreauef9a3602012-12-08 22:29:20 +01005044 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5045 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5046 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5047 curproxy->conn_src.bind_hdr_len = end - name;
5048 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5049 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5050 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005051
5052 /* now look for an occurrence number */
5053 while (isspace(*end))
5054 end++;
5055 if (*end == ',') {
5056 end++;
5057 name = end;
5058 if (*end == '-')
5059 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005060 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005061 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005062 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005063 }
5064
Willy Tarreauef9a3602012-12-08 22:29:20 +01005065 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005066 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5067 " occurrences values smaller than %d.\n",
5068 file, linenum, MAX_HDR_HISTORY);
5069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
5071 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005072 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005073 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005074
Willy Tarreau902636f2013-03-10 19:44:48 +01005075 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005076 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005077 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005078 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005079 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005080 goto out;
5081 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005082
5083 proto = protocol_by_family(sk->ss_family);
5084 if (!proto || !proto->connect) {
5085 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5086 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
5089 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005090
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005091 if (port1 != port2) {
5092 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5093 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
5096 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005097 curproxy->conn_src.tproxy_addr = *sk;
5098 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005099 }
5100 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005101#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005102 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005103#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005104#else /* no TPROXY support */
5105 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005106 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005109#endif
5110 cur_arg += 2;
5111 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005112 }
5113
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005114 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5115#ifdef SO_BINDTODEVICE
5116 if (!*args[cur_arg + 1]) {
5117 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5118 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005121 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005122 free(curproxy->conn_src.iface_name);
5123 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5124 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005125 global.last_checks |= LSTCHK_NETADM;
5126#else
5127 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5128 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005131#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005132 cur_arg += 2;
5133 continue;
5134 }
5135 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005136 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005139 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005141 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5142 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5143 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5150 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154
5155 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005156 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005157 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
5161 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005163 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005164 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
5168 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005169 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005170 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005171 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
5175 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005177 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005178 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005179 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
5182 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005184 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005185 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005189 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005191 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005192 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005194 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005195 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005196 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005198 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005199 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005201 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005202
5203 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5204 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 +01005205 }
5206 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005208 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005209 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005211 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005212
5213 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5214 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 +01005215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5219 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005223
5224 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005225 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005226 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
5230 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005232 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005233 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 }
5237 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005239 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005240 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005241 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 }
5244 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005246 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005247 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005248 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 }
5251 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005253 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005254 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005255 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005258 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005260 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005261 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005263 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005266 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005267
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 if (curproxy == &defproxy) {
5269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005273 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005274 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 if (*(args[1]) == 0) {
5277 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005278 err_code |= ERR_ALERT | ERR_FATAL;
5279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005281
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005282 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005283 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5284 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5285 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005289 err_code |= warnif_cond_conflicts(cond,
5290 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5291 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005292 }
5293 else if (*args[2]) {
5294 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5295 file, linenum, args[0], args[2]);
5296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
5298 }
5299
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005300 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005301 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005302 wl->s = strdup(args[1]);
5303 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005304 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
5306 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5309 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005313
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005315 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005316 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 }
5320 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005322 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005323 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005324 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
5327 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005329 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005330 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005331 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 }
5334 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 }
5341
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005343 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005344 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005345 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
5348 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005349 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005350 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005351 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005352 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005354 }
5355 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005356 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005357 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005358 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005359 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 }
5362 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005363 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005364
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 if (curproxy == &defproxy) {
5366 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005370 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005371 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 if (*(args[1]) == 0) {
5374 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
5378
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005379 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005380 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5381 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5382 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
5385 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005386 err_code |= warnif_cond_conflicts(cond,
5387 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5388 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005389 }
5390 else if (*args[2]) {
5391 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5392 file, linenum, args[0], args[2]);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
5396
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005397 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005398 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005399 wl->s = strdup(args[1]);
5400 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
5402 else if (!strcmp(args[0], "errorloc") ||
5403 !strcmp(args[0], "errorloc302") ||
5404 !strcmp(args[0], "errorloc303")) { /* error location */
5405 int errnum, errlen;
5406 char *err;
5407
Willy Tarreau977b8e42006-12-29 14:19:17 +01005408 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005409 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005410
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005412 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 }
5416
5417 errnum = atol(args[1]);
5418 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005419 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5420 err = malloc(errlen);
5421 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005423 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5424 err = malloc(errlen);
5425 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
5427
Willy Tarreau0f772532006-12-23 20:51:41 +01005428 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5429 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005430 chunk_destroy(&curproxy->errmsg[rc]);
5431 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005432 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005434 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005435
5436 if (rc >= HTTP_ERR_SIZE) {
5437 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5438 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005439 free(err);
5440 }
5441 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005442 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5443 int errnum, errlen, fd;
5444 char *err;
5445 struct stat stat;
5446
5447 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005448 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005449
5450 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005451 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005454 }
5455
5456 fd = open(args[2], O_RDONLY);
5457 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5458 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5459 file, linenum, args[2], args[1]);
5460 if (fd >= 0)
5461 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005464 }
5465
Willy Tarreau27a674e2009-08-17 07:23:33 +02005466 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005467 errlen = stat.st_size;
5468 } else {
5469 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005470 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005471 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005472 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005473 }
5474
5475 err = malloc(errlen); /* malloc() must succeed during parsing */
5476 errnum = read(fd, err, errlen);
5477 if (errnum != errlen) {
5478 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5479 file, linenum, args[2], args[1]);
5480 close(fd);
5481 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005484 }
5485 close(fd);
5486
5487 errnum = atol(args[1]);
5488 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5489 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005490 chunk_destroy(&curproxy->errmsg[rc]);
5491 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005492 break;
5493 }
5494 }
5495
5496 if (rc >= HTTP_ERR_SIZE) {
5497 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5498 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005499 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500 free(err);
5501 }
5502 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005503 else if (!strcmp(args[0], "compression")) {
5504 struct comp *comp;
5505 if (curproxy->comp == NULL) {
5506 comp = calloc(1, sizeof(struct comp));
5507 curproxy->comp = comp;
5508 } else {
5509 comp = curproxy->comp;
5510 }
5511
5512 if (!strcmp(args[1], "algo")) {
5513 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005514 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005515
William Lallemand82fe75c2012-10-23 10:25:10 +02005516 cur_arg = 2;
5517 if (!*args[cur_arg]) {
5518 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5519 file, linenum, args[0]);
5520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522 }
5523 while (*(args[cur_arg])) {
5524 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5525 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5526 file, linenum, args[0], args[cur_arg]);
5527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
William Lallemand552df672012-11-07 13:21:47 +01005530 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5531 curproxy->comp->algos->end(&ctx);
5532 } else {
5533 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5534 file, linenum, args[0], args[cur_arg]);
5535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
5537 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005538 cur_arg ++;
5539 continue;
5540 }
5541 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005542 else if (!strcmp(args[1], "offload")) {
5543 comp->offload = 1;
5544 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005545 else if (!strcmp(args[1], "type")) {
5546 int cur_arg;
5547 cur_arg = 2;
5548 if (!*args[cur_arg]) {
5549 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5550 file, linenum, args[0]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554 while (*(args[cur_arg])) {
5555 comp_append_type(comp, args[cur_arg]);
5556 cur_arg ++;
5557 continue;
5558 }
5559 }
5560 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005561 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005562 file, linenum, args[0]);
5563 err_code |= ERR_ALERT | ERR_FATAL;
5564 goto out;
5565 }
5566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005568 struct cfg_kw_list *kwl;
5569 int index;
5570
5571 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5572 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5573 if (kwl->kw[index].section != CFG_LISTEN)
5574 continue;
5575 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5576 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005577 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005578 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005579 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005580 err_code |= ERR_ALERT | ERR_FATAL;
5581 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005582 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005583 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005584 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005585 err_code |= ERR_WARN;
5586 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005587 }
Willy Tarreau93893792009-07-23 13:19:11 +02005588 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005589 }
5590 }
5591 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005592
Willy Tarreau6daf3432008-01-22 16:44:08 +01005593 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 }
Willy Tarreau93893792009-07-23 13:19:11 +02005597 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005598 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005599 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600}
5601
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005602int
5603cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5604{
5605
5606 int err_code = 0;
5607 const char *err;
5608
5609 if (!strcmp(args[0], "userlist")) { /* new userlist */
5610 struct userlist *newul;
5611
5612 if (!*args[1]) {
5613 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5614 file, linenum, args[0]);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 }
5618
5619 err = invalid_char(args[1]);
5620 if (err) {
5621 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5622 file, linenum, *err, args[0], args[1]);
5623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
5626
5627 for (newul = userlist; newul; newul = newul->next)
5628 if (!strcmp(newul->name, args[1])) {
5629 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5630 file, linenum, args[1]);
5631 err_code |= ERR_WARN;
5632 goto out;
5633 }
5634
5635 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5636 if (!newul) {
5637 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5638 err_code |= ERR_ALERT | ERR_ABORT;
5639 goto out;
5640 }
5641
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005642 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005643 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005644 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5645 err_code |= ERR_ALERT | ERR_ABORT;
5646 goto out;
5647 }
5648
5649 newul->next = userlist;
5650 userlist = newul;
5651
5652 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005653 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005654 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005655 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005656
5657 if (!*args[1]) {
5658 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5659 file, linenum, args[0]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663
5664 err = invalid_char(args[1]);
5665 if (err) {
5666 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5667 file, linenum, *err, args[0], args[1]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671
William Lallemandfaf33152015-05-28 18:03:51 +02005672 if (!userlist)
5673 goto out;
5674
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005675 for (ag = userlist->groups; ag; ag = ag->next)
5676 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005677 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5678 file, linenum, args[1], userlist->name);
5679 err_code |= ERR_ALERT;
5680 goto out;
5681 }
5682
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005683 ag = calloc(1, sizeof(*ag));
5684 if (!ag) {
5685 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5686 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005687 goto out;
5688 }
5689
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005690 ag->name = strdup(args[1]);
5691 if (!ag) {
5692 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5693 err_code |= ERR_ALERT | ERR_ABORT;
5694 goto out;
5695 }
5696
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005697 cur_arg = 2;
5698
5699 while (*args[cur_arg]) {
5700 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005701 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005702 cur_arg += 2;
5703 continue;
5704 } else {
5705 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5706 file, linenum, args[0]);
5707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
5709 }
5710 }
5711
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005712 ag->next = userlist->groups;
5713 userlist->groups = ag;
5714
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005715 } else if (!strcmp(args[0], "user")) { /* new user */
5716 struct auth_users *newuser;
5717 int cur_arg;
5718
5719 if (!*args[1]) {
5720 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5721 file, linenum, args[0]);
5722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
5724 }
William Lallemandfaf33152015-05-28 18:03:51 +02005725 if (!userlist)
5726 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005727
5728 for (newuser = userlist->users; newuser; newuser = newuser->next)
5729 if (!strcmp(newuser->user, args[1])) {
5730 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5731 file, linenum, args[1], userlist->name);
5732 err_code |= ERR_ALERT;
5733 goto out;
5734 }
5735
5736 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5737 if (!newuser) {
5738 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5739 err_code |= ERR_ALERT | ERR_ABORT;
5740 goto out;
5741 }
5742
5743 newuser->user = strdup(args[1]);
5744
5745 newuser->next = userlist->users;
5746 userlist->users = newuser;
5747
5748 cur_arg = 2;
5749
5750 while (*args[cur_arg]) {
5751 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005752#ifdef CONFIG_HAP_CRYPT
5753 if (!crypt("", args[cur_arg + 1])) {
5754 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5755 file, linenum, newuser->user);
5756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
5758 }
5759#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005760 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5761 file, linenum);
5762 err_code |= ERR_ALERT;
5763#endif
5764 newuser->pass = strdup(args[cur_arg + 1]);
5765 cur_arg += 2;
5766 continue;
5767 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5768 newuser->pass = strdup(args[cur_arg + 1]);
5769 newuser->flags |= AU_O_INSECURE;
5770 cur_arg += 2;
5771 continue;
5772 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005773 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005774 cur_arg += 2;
5775 continue;
5776 } else {
5777 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5778 file, linenum, args[0]);
5779 err_code |= ERR_ALERT | ERR_FATAL;
5780 goto out;
5781 }
5782 }
5783 } else {
5784 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5785 err_code |= ERR_ALERT | ERR_FATAL;
5786 }
5787
5788out:
5789 return err_code;
5790}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791
5792/*
5793 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005794 * Returns the error code, 0 if OK, or any combination of :
5795 * - ERR_ABORT: must abort ASAP
5796 * - ERR_FATAL: we can continue parsing but not start the service
5797 * - ERR_WARN: a warning has been emitted
5798 * - ERR_ALERT: an alert has been emitted
5799 * Only the two first ones can stop processing, the two others are just
5800 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005802int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005804 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 FILE *f;
5806 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005807 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005808 struct cfg_section *cs = NULL;
5809 struct cfg_section *ics;
5810
5811 /* Register internal sections */
5812 if (!cfg_register_section("listen", cfg_parse_listen) ||
5813 !cfg_register_section("frontend", cfg_parse_listen) ||
5814 !cfg_register_section("backend", cfg_parse_listen) ||
5815 !cfg_register_section("ruleset", cfg_parse_listen) ||
5816 !cfg_register_section("defaults", cfg_parse_listen) ||
5817 !cfg_register_section("global", cfg_parse_global) ||
5818 !cfg_register_section("userlist", cfg_parse_users) ||
5819 !cfg_register_section("peers", cfg_parse_peers))
5820 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 if ((f=fopen(file,"r")) == NULL)
5823 return -1;
5824
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005825 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005826 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005827 char *end;
5828 char *args[MAX_LINE_ARGS + 1];
5829 char *line = thisline;
5830
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 linenum++;
5832
5833 end = line + strlen(line);
5834
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005835 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5836 /* Check if we reached the limit and the last char is not \n.
5837 * Watch out for the last line without the terminating '\n'!
5838 */
5839 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005840 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005841 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005842 }
5843
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005845 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 line++;
5847
5848 arg = 0;
5849 args[arg] = line;
5850
5851 while (*line && arg < MAX_LINE_ARGS) {
5852 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5853 * C equivalent value. Other combinations left unchanged (eg: \1).
5854 */
5855 if (*line == '\\') {
5856 int skip = 0;
5857 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5858 *line = line[1];
5859 skip = 1;
5860 }
5861 else if (line[1] == 'r') {
5862 *line = '\r';
5863 skip = 1;
5864 }
5865 else if (line[1] == 'n') {
5866 *line = '\n';
5867 skip = 1;
5868 }
5869 else if (line[1] == 't') {
5870 *line = '\t';
5871 skip = 1;
5872 }
5873 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005874 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005875 unsigned char hex1, hex2;
5876 hex1 = toupper(line[2]) - '0';
5877 hex2 = toupper(line[3]) - '0';
5878 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5879 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5880 *line = (hex1<<4) + hex2;
5881 skip = 3;
5882 }
5883 else {
5884 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005885 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 }
5887 }
5888 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005889 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005890 end -= skip;
5891 }
5892 line++;
5893 }
5894 else if (*line == '#' || *line == '\n' || *line == '\r') {
5895 /* end of string, end of loop */
5896 *line = 0;
5897 break;
5898 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005899 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005900 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005901 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005902 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903 line++;
5904 args[++arg] = line;
5905 }
5906 else {
5907 line++;
5908 }
5909 }
5910
5911 /* empty line */
5912 if (!**args)
5913 continue;
5914
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005915 if (*line) {
5916 /* we had to stop due to too many args.
5917 * Let's terminate the string, print the offending part then cut the
5918 * last arg.
5919 */
5920 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5921 line++;
5922 *line = '\0';
5923
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005924 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005925 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005926 err_code |= ERR_ALERT | ERR_FATAL;
5927 args[arg] = line;
5928 }
5929
Willy Tarreau540abe42007-05-02 20:50:16 +02005930 /* zero out remaining args and ensure that at least one entry
5931 * is zeroed out.
5932 */
5933 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005934 args[arg] = line;
5935 }
5936
Willy Tarreau3842f002009-06-14 11:39:52 +02005937 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005938 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005939 char *tmp;
5940
Willy Tarreau3842f002009-06-14 11:39:52 +02005941 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005942 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005943 for (arg=0; *args[arg+1]; arg++)
5944 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005945 *tmp = '\0'; // fix the next arg to \0
5946 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005947 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005948 else if (!strcmp(args[0], "default")) {
5949 kwm = KWM_DEF;
5950 for (arg=0; *args[arg+1]; arg++)
5951 args[arg] = args[arg+1]; // shift args after inversion
5952 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005953
William Lallemand0f99e342011-10-12 17:50:54 +02005954 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5955 strcmp(args[0], "log") != 0) {
5956 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005957 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005958 }
5959
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005960 /* detect section start */
5961 list_for_each_entry(ics, &sections, list) {
5962 if (strcmp(args[0], ics->section_name) == 0) {
5963 cursection = ics->section_name;
5964 cs = ics;
5965 break;
5966 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005967 }
5968
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005970 if (cs)
5971 err_code |= cs->section_parser(file, linenum, args, kwm);
5972 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005973 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005974 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005976
5977 if (err_code & ERR_ABORT)
5978 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005979 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005980 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005982 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005983}
5984
Willy Tarreau5436afc2014-09-16 12:17:36 +02005985/* This function propagates processes from frontend <from> to backend <to> so
5986 * that it is always guaranteed that a backend pointed to by a frontend is
5987 * bound to all of its processes. After that, if the target is a "listen"
5988 * instance, the function recursively descends the target's own targets along
5989 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
5990 * checked first to ensure that <to> is already bound to all processes of
5991 * <from>, there is no risk of looping and we ensure to follow the shortest
5992 * path to the destination.
5993 *
5994 * It is possible to set <to> to NULL for the first call so that the function
5995 * takes care of visiting the initial frontend in <from>.
5996 *
5997 * It is important to note that the function relies on the fact that all names
5998 * have already been resolved.
5999 */
6000void propagate_processes(struct proxy *from, struct proxy *to)
6001{
6002 struct switching_rule *rule;
6003 struct hdr_exp *exp;
6004
6005 if (to) {
6006 /* check whether we need to go down */
6007 if (from->bind_proc &&
6008 (from->bind_proc & to->bind_proc) == from->bind_proc)
6009 return;
6010
6011 if (!from->bind_proc && !to->bind_proc)
6012 return;
6013
6014 to->bind_proc = from->bind_proc ?
6015 (to->bind_proc | from->bind_proc) : 0;
6016
6017 /* now propagate down */
6018 from = to;
6019 }
6020
Willy Tarreau7110f382014-12-18 13:56:26 +01006021 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006022 return;
6023
Willy Tarreaued061c02014-12-18 14:00:43 +01006024 if (from->state == PR_STSTOPPED)
6025 return;
6026
Willy Tarreau5436afc2014-09-16 12:17:36 +02006027 /* default_backend */
6028 if (from->defbe.be)
6029 propagate_processes(from, from->defbe.be);
6030
6031 /* use_backend */
6032 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006033 if (rule->dynamic)
6034 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006035 to = rule->be.backend;
6036 propagate_processes(from, to);
6037 }
6038
6039 /* reqsetbe */
6040 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6041 if (exp->action != ACT_SETBE)
6042 continue;
6043 to = (struct proxy *)exp->replace;
6044 propagate_processes(from, to);
6045 }
6046}
6047
Willy Tarreaubb925012009-07-23 13:36:36 +02006048/*
6049 * Returns the error code, 0 if OK, or any combination of :
6050 * - ERR_ABORT: must abort ASAP
6051 * - ERR_FATAL: we can continue parsing but not start the service
6052 * - ERR_WARN: a warning has been emitted
6053 * - ERR_ALERT: an alert has been emitted
6054 * Only the two first ones can stop processing, the two others are just
6055 * indicators.
6056 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006057int check_config_validity()
6058{
6059 int cfgerr = 0;
6060 struct proxy *curproxy = NULL;
6061 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006062 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006063 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006064 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006066 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067 /*
6068 * Now, check for the integrity of all that we have collected.
6069 */
6070
6071 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006072 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006073
Willy Tarreau193b8c62012-11-22 00:17:38 +01006074 if (!global.tune.max_http_hdr)
6075 global.tune.max_http_hdr = MAX_HTTP_HDR;
6076
6077 if (!global.tune.cookie_len)
6078 global.tune.cookie_len = CAPTURE_LEN;
6079
6080 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6081
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006082 /* Post initialisation of the users and groups lists. */
6083 err_code = userlist_postinit();
6084 if (err_code != ERR_NONE)
6085 goto out;
6086
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006087 /* first, we will invert the proxy list order */
6088 curproxy = NULL;
6089 while (proxy) {
6090 struct proxy *next;
6091
6092 next = proxy->next;
6093 proxy->next = curproxy;
6094 curproxy = proxy;
6095 if (!next)
6096 break;
6097 proxy = next;
6098 }
6099
Willy Tarreau91b00c22014-09-16 13:41:21 +02006100 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006101 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006102 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006103 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006104 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006105 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006106 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006107
Willy Tarreau050536d2012-10-04 08:47:34 +02006108 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006109 /* proxy ID not set, use automatic numbering with first
6110 * spare entry starting with next_pxid.
6111 */
6112 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6113 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6114 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006115 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006116 next_pxid++;
6117
Willy Tarreau55ea7572007-06-17 19:56:27 +02006118
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006120 /* ensure we don't keep listeners uselessly bound */
6121 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006122 free((void *)curproxy->table.peers.name);
6123 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124 continue;
6125 }
6126
Willy Tarreau102df612014-05-07 23:56:38 +02006127 /* Check multi-process mode compatibility for the current proxy */
6128
6129 if (curproxy->bind_proc) {
6130 /* an explicit bind-process was specified, let's check how many
6131 * processes remain.
6132 */
6133 nbproc = popcount(curproxy->bind_proc);
6134
6135 curproxy->bind_proc &= nbits(global.nbproc);
6136 if (!curproxy->bind_proc && nbproc == 1) {
6137 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);
6138 curproxy->bind_proc = 1;
6139 }
6140 else if (!curproxy->bind_proc && nbproc > 1) {
6141 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);
6142 curproxy->bind_proc = 0;
6143 }
6144 }
6145
Willy Tarreau3d209582014-05-09 17:06:11 +02006146 /* check and reduce the bind-proc of each listener */
6147 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6148 unsigned long mask;
6149
6150 if (!bind_conf->bind_proc)
6151 continue;
6152
6153 mask = nbits(global.nbproc);
6154 if (curproxy->bind_proc)
6155 mask &= curproxy->bind_proc;
6156 /* mask cannot be null here thanks to the previous checks */
6157
6158 nbproc = popcount(bind_conf->bind_proc);
6159 bind_conf->bind_proc &= mask;
6160
6161 if (!bind_conf->bind_proc && nbproc == 1) {
6162 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",
6163 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6164 bind_conf->bind_proc = mask & ~(mask - 1);
6165 }
6166 else if (!bind_conf->bind_proc && nbproc > 1) {
6167 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",
6168 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6169 bind_conf->bind_proc = 0;
6170 }
6171 }
6172
Willy Tarreau102df612014-05-07 23:56:38 +02006173 if (global.nbproc > 1 && curproxy->table.peers.name) {
6174 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6175 curproxy->id);
6176 cfgerr++;
6177 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006178
Willy Tarreauff01a212009-03-15 13:46:16 +01006179 switch (curproxy->mode) {
6180 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006181 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006182 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006183 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6184 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006185 cfgerr++;
6186 }
6187
6188 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006189 Warning("config : servers will be ignored for %s '%s'.\n",
6190 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006191 break;
6192
6193 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006194 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006195 break;
6196
6197 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006198 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006199 break;
6200 }
6201
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006202 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006203 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006204 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006205 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6206 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006207 cfgerr++;
6208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006210 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006211 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6212 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006213 cfgerr++;
6214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006216 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006217 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6218 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006219 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006220 }
6221 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006222 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006223 /* If no LB algo is set in a backend, and we're not in
6224 * transparent mode, dispatch mode nor proxy mode, we
6225 * want to use balance roundrobin by default.
6226 */
6227 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6228 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 }
6230 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006231
Willy Tarreau1620ec32011-08-06 17:05:02 +02006232 if (curproxy->options & PR_O_DISPATCH)
6233 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6234 else if (curproxy->options & PR_O_HTTP_PROXY)
6235 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6236 else if (curproxy->options & PR_O_TRANSP)
6237 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006238
Willy Tarreau1620ec32011-08-06 17:05:02 +02006239 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6240 if (curproxy->options & PR_O_DISABLE404) {
6241 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6242 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6243 err_code |= ERR_WARN;
6244 curproxy->options &= ~PR_O_DISABLE404;
6245 }
6246 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6247 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6248 "send-state", proxy_type_str(curproxy), curproxy->id);
6249 err_code |= ERR_WARN;
6250 curproxy->options &= ~PR_O2_CHK_SNDST;
6251 }
Willy Tarreauef781042010-01-27 11:53:01 +01006252 }
6253
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006254 /* if a default backend was specified, let's find it */
6255 if (curproxy->defbe.name) {
6256 struct proxy *target;
6257
Alex Williams96532db2009-11-01 21:27:13 -05006258 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006259 if (!target) {
6260 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6261 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006262 cfgerr++;
6263 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006264 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6265 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006266 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006267 } else {
6268 free(curproxy->defbe.name);
6269 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006270
6271 /* Emit a warning if this proxy also has some servers */
6272 if (curproxy->srv) {
6273 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6274 curproxy->id);
6275 err_code |= ERR_WARN;
6276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 }
6278 }
6279
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006280 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006281 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6282 /* map jump target for ACT_SETBE in req_rep chain */
6283 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006284 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006285 struct proxy *target;
6286
Willy Tarreaua496b602006-12-17 23:15:24 +01006287 if (exp->action != ACT_SETBE)
6288 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006289
Alex Williams96532db2009-11-01 21:27:13 -05006290 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006291 if (!target) {
6292 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6293 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006294 cfgerr++;
6295 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006296 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6297 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006298 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006299 } else {
6300 free((void *)exp->replace);
6301 exp->replace = (const char *)target;
6302 }
6303 }
6304 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006305
6306 /* find the target proxy for 'use_backend' rules */
6307 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006308 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006309 struct logformat_node *node;
6310 char *pxname;
6311
6312 /* Try to parse the string as a log format expression. If the result
6313 * of the parsing is only one entry containing a simple string, then
6314 * it's a standard string corresponding to a static rule, thus the
6315 * parsing is cancelled and be.name is restored to be resolved.
6316 */
6317 pxname = rule->be.name;
6318 LIST_INIT(&rule->be.expr);
6319 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6320 curproxy->conf.args.file, curproxy->conf.args.line);
6321 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6322
6323 if (!LIST_ISEMPTY(&rule->be.expr)) {
6324 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6325 rule->dynamic = 1;
6326 free(pxname);
6327 continue;
6328 }
6329 /* simple string: free the expression and fall back to static rule */
6330 free(node->arg);
6331 free(node);
6332 }
6333
6334 rule->dynamic = 0;
6335 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006336
Alex Williams96532db2009-11-01 21:27:13 -05006337 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006338
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006339 if (!target) {
6340 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6341 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006342 cfgerr++;
6343 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006344 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6345 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006346 cfgerr++;
6347 } else {
6348 free((void *)rule->be.name);
6349 rule->be.backend = target;
6350 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006351 }
6352
Willy Tarreau5436afc2014-09-16 12:17:36 +02006353 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006354 list_for_each_entry(srule, &curproxy->server_rules, list) {
6355 struct server *target = findserver(curproxy, srule->srv.name);
6356
6357 if (!target) {
6358 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6359 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6360 cfgerr++;
6361 continue;
6362 }
6363 free((void *)srule->srv.name);
6364 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006365 }
6366
Emeric Brunb982a3d2010-01-04 15:45:53 +01006367 /* find the target table for 'stick' rules */
6368 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6369 struct proxy *target;
6370
Emeric Brun1d33b292010-01-04 15:47:17 +01006371 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6372 if (mrule->flags & STK_IS_STORE)
6373 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6374
Emeric Brunb982a3d2010-01-04 15:45:53 +01006375 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006376 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006377 else
6378 target = curproxy;
6379
6380 if (!target) {
6381 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6382 curproxy->id, mrule->table.name);
6383 cfgerr++;
6384 }
6385 else if (target->table.size == 0) {
6386 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6387 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6388 cfgerr++;
6389 }
Willy Tarreau12785782012-04-27 21:37:17 +02006390 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6391 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006392 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6393 cfgerr++;
6394 }
6395 else {
6396 free((void *)mrule->table.name);
6397 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006398 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006399 }
6400 }
6401
6402 /* find the target table for 'store response' rules */
6403 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6404 struct proxy *target;
6405
Emeric Brun1d33b292010-01-04 15:47:17 +01006406 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6407
Emeric Brunb982a3d2010-01-04 15:45:53 +01006408 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006409 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006410 else
6411 target = curproxy;
6412
6413 if (!target) {
6414 Alert("Proxy '%s': unable to find store table '%s'.\n",
6415 curproxy->id, mrule->table.name);
6416 cfgerr++;
6417 }
6418 else if (target->table.size == 0) {
6419 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6420 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6421 cfgerr++;
6422 }
Willy Tarreau12785782012-04-27 21:37:17 +02006423 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6424 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006425 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6426 cfgerr++;
6427 }
6428 else {
6429 free((void *)mrule->table.name);
6430 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006431 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006432 }
6433 }
6434
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006435 /* find the target table for 'tcp-request' layer 4 rules */
6436 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6437 struct proxy *target;
6438
Willy Tarreaub4c84932013-07-23 19:15:30 +02006439 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006440 continue;
6441
6442 if (trule->act_prm.trk_ctr.table.n)
6443 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6444 else
6445 target = curproxy;
6446
6447 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006448 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6449 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006450 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006451 cfgerr++;
6452 }
6453 else if (target->table.size == 0) {
6454 Alert("Proxy '%s': table '%s' used but not configured.\n",
6455 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6456 cfgerr++;
6457 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006458 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6459 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6460 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 +01006461 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006462 cfgerr++;
6463 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006464 else {
6465 free(trule->act_prm.trk_ctr.table.n);
6466 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006467 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006468 * to pass a list of counters to track and allocate them right here using
6469 * stktable_alloc_data_type().
6470 */
6471 }
6472 }
6473
Willy Tarreaud1f96522010-08-03 19:34:32 +02006474 /* find the target table for 'tcp-request' layer 6 rules */
6475 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6476 struct proxy *target;
6477
Willy Tarreaub4c84932013-07-23 19:15:30 +02006478 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006479 continue;
6480
6481 if (trule->act_prm.trk_ctr.table.n)
6482 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6483 else
6484 target = curproxy;
6485
6486 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006487 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6488 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006489 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006490 cfgerr++;
6491 }
6492 else if (target->table.size == 0) {
6493 Alert("Proxy '%s': table '%s' used but not configured.\n",
6494 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6495 cfgerr++;
6496 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006497 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6498 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6499 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 +01006500 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006501 cfgerr++;
6502 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006503 else {
6504 free(trule->act_prm.trk_ctr.table.n);
6505 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006506 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006507 * to pass a list of counters to track and allocate them right here using
6508 * stktable_alloc_data_type().
6509 */
6510 }
6511 }
6512
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006513 /* move any "block" rules at the beginning of the http-request rules */
6514 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6515 /* insert block_rules into http_req_rules at the beginning */
6516 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6517 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6518 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6519 curproxy->http_req_rules.n = curproxy->block_rules.n;
6520 LIST_INIT(&curproxy->block_rules);
6521 }
6522
Emeric Brun32da3c42010-09-23 18:39:19 +02006523 if (curproxy->table.peers.name) {
6524 struct peers *curpeers = peers;
6525
6526 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6527 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6528 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006529 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006530 break;
6531 }
6532 }
6533
6534 if (!curpeers) {
6535 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6536 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006537 free((void *)curproxy->table.peers.name);
6538 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006539 cfgerr++;
6540 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006541 else if (curpeers->state == PR_STSTOPPED) {
6542 /* silently disable this peers section */
6543 curproxy->table.peers.p = NULL;
6544 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006545 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006546 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6547 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006548 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006549 cfgerr++;
6550 }
6551 }
6552
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006553 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006554 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006555 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6556 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6557 "proxy", curproxy->id);
6558 cfgerr++;
6559 goto out_uri_auth_compat;
6560 }
6561
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006562 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006563 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006564 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006565 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006566
Willy Tarreau95fa4692010-02-01 13:05:50 +01006567 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6568 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006569
6570 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006571 uri_auth_compat_req[i++] = "realm";
6572 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6573 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006574
Willy Tarreau95fa4692010-02-01 13:05:50 +01006575 uri_auth_compat_req[i++] = "unless";
6576 uri_auth_compat_req[i++] = "{";
6577 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6578 uri_auth_compat_req[i++] = "}";
6579 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006580
Willy Tarreauff011f22011-01-06 17:51:27 +01006581 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6582 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006583 cfgerr++;
6584 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006585 }
6586
Willy Tarreauff011f22011-01-06 17:51:27 +01006587 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006588
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006589 if (curproxy->uri_auth->auth_realm) {
6590 free(curproxy->uri_auth->auth_realm);
6591 curproxy->uri_auth->auth_realm = NULL;
6592 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006593
6594 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006595 }
6596out_uri_auth_compat:
6597
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006598 /* compile the log format */
6599 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006600 if (curproxy->conf.logformat_string != default_http_log_format &&
6601 curproxy->conf.logformat_string != default_tcp_log_format &&
6602 curproxy->conf.logformat_string != clf_http_log_format)
6603 free(curproxy->conf.logformat_string);
6604 curproxy->conf.logformat_string = NULL;
6605 free(curproxy->conf.lfs_file);
6606 curproxy->conf.lfs_file = NULL;
6607 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006608 }
6609
Willy Tarreau62a61232013-04-12 18:13:46 +02006610 if (curproxy->conf.logformat_string) {
6611 curproxy->conf.args.ctx = ARGC_LOG;
6612 curproxy->conf.args.file = curproxy->conf.lfs_file;
6613 curproxy->conf.args.line = curproxy->conf.lfs_line;
6614 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006615 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006616 curproxy->conf.args.file = NULL;
6617 curproxy->conf.args.line = 0;
6618 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006619
Willy Tarreau62a61232013-04-12 18:13:46 +02006620 if (curproxy->conf.uniqueid_format_string) {
6621 curproxy->conf.args.ctx = ARGC_UIF;
6622 curproxy->conf.args.file = curproxy->conf.uif_file;
6623 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006624 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006625 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006626 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006627 curproxy->conf.args.file = NULL;
6628 curproxy->conf.args.line = 0;
6629 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006630
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006631 /* only now we can check if some args remain unresolved.
6632 * This must be done after the users and groups resolution.
6633 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006634 cfgerr += smp_resolve_args(curproxy);
6635 if (!cfgerr)
6636 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006637
Willy Tarreau2738a142006-07-08 17:28:09 +02006638 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006639 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006640 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006641 (!curproxy->timeout.connect ||
6642 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006643 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006644 " | While not properly invalid, you will certainly encounter various problems\n"
6645 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006646 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006647 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006648 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006649 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006650
Willy Tarreau1fa31262007-12-03 00:36:16 +01006651 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6652 * We must still support older configurations, so let's find out whether those
6653 * parameters have been set or must be copied from contimeouts.
6654 */
6655 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006656 if (!curproxy->timeout.tarpit ||
6657 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006658 /* tarpit timeout not set. We search in the following order:
6659 * default.tarpit, curr.connect, default.connect.
6660 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006661 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006662 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006663 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006664 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006665 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006666 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006667 }
6668 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006669 (!curproxy->timeout.queue ||
6670 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006671 /* queue timeout not set. We search in the following order:
6672 * default.queue, curr.connect, default.connect.
6673 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006674 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006675 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006676 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006677 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006678 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006679 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006680 }
6681 }
6682
Willy Tarreau1620ec32011-08-06 17:05:02 +02006683 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006684 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6685 curproxy->check_req = (char *)malloc(curproxy->check_len);
6686 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006687 }
6688
Willy Tarreau215663d2014-06-13 18:30:23 +02006689 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6690 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6691 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6692 proxy_type_str(curproxy), curproxy->id);
6693 err_code |= ERR_WARN;
6694 }
6695
Willy Tarreau193b8c62012-11-22 00:17:38 +01006696 /* ensure that cookie capture length is not too large */
6697 if (curproxy->capture_len >= global.tune.cookie_len) {
6698 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6699 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6700 err_code |= ERR_WARN;
6701 curproxy->capture_len = global.tune.cookie_len - 1;
6702 }
6703
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006704 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006705 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006706 curproxy->req_cap_pool = create_pool("ptrcap",
6707 curproxy->nb_req_cap * sizeof(char *),
6708 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006709 }
6710
6711 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006712 curproxy->rsp_cap_pool = create_pool("ptrcap",
6713 curproxy->nb_rsp_cap * sizeof(char *),
6714 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006715 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006716
Willy Tarreaubaaee002006-06-26 02:48:02 +02006717 /* first, we will invert the servers list order */
6718 newsrv = NULL;
6719 while (curproxy->srv) {
6720 struct server *next;
6721
6722 next = curproxy->srv->next;
6723 curproxy->srv->next = newsrv;
6724 newsrv = curproxy->srv;
6725 if (!next)
6726 break;
6727 curproxy->srv = next;
6728 }
6729
Willy Tarreau17edc812014-01-03 12:14:34 +01006730 /* Check that no server name conflicts. This causes trouble in the stats.
6731 * We only emit a warning for the first conflict affecting each server,
6732 * in order to avoid combinatory explosion if all servers have the same
6733 * name. We do that only for servers which do not have an explicit ID,
6734 * because these IDs were made also for distinguishing them and we don't
6735 * want to annoy people who correctly manage them.
6736 */
6737 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6738 struct server *other_srv;
6739
6740 if (newsrv->puid)
6741 continue;
6742
6743 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6744 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6745 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6746 newsrv->conf.file, newsrv->conf.line,
6747 proxy_type_str(curproxy), curproxy->id,
6748 newsrv->id, other_srv->conf.line);
6749 break;
6750 }
6751 }
6752 }
6753
Willy Tarreaudd701652010-05-25 23:03:02 +02006754 /* assign automatic UIDs to servers which don't have one yet */
6755 next_id = 1;
6756 newsrv = curproxy->srv;
6757 while (newsrv != NULL) {
6758 if (!newsrv->puid) {
6759 /* server ID not set, use automatic numbering with first
6760 * spare entry starting with next_svid.
6761 */
6762 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6763 newsrv->conf.id.key = newsrv->puid = next_id;
6764 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6765 }
6766 next_id++;
6767 newsrv = newsrv->next;
6768 }
6769
Willy Tarreau20697042007-11-15 23:26:18 +01006770 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006771 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006772
Willy Tarreau62c3be22012-01-20 13:12:32 +01006773 /*
6774 * If this server supports a maxconn parameter, it needs a dedicated
6775 * tasks to fill the emptied slots when a connection leaves.
6776 * Also, resolve deferred tracking dependency if needed.
6777 */
6778 newsrv = curproxy->srv;
6779 while (newsrv != NULL) {
6780 if (newsrv->minconn > newsrv->maxconn) {
6781 /* Only 'minconn' was specified, or it was higher than or equal
6782 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6783 * this will avoid further useless expensive computations.
6784 */
6785 newsrv->maxconn = newsrv->minconn;
6786 } else if (newsrv->maxconn && !newsrv->minconn) {
6787 /* minconn was not specified, so we set it to maxconn */
6788 newsrv->minconn = newsrv->maxconn;
6789 }
6790
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006791#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006792 if (newsrv->use_ssl || newsrv->check.use_ssl)
6793 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006794#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006795
Willy Tarreau2f075e92013-12-03 11:11:34 +01006796 /* set the check type on the server */
6797 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6798
Willy Tarreau62c3be22012-01-20 13:12:32 +01006799 if (newsrv->trackit) {
6800 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006801 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006802 char *pname, *sname;
6803
6804 pname = newsrv->trackit;
6805 sname = strrchr(pname, '/');
6806
6807 if (sname)
6808 *sname++ = '\0';
6809 else {
6810 sname = pname;
6811 pname = NULL;
6812 }
6813
6814 if (pname) {
6815 px = findproxy(pname, PR_CAP_BE);
6816 if (!px) {
6817 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6818 proxy_type_str(curproxy), curproxy->id,
6819 newsrv->id, pname);
6820 cfgerr++;
6821 goto next_srv;
6822 }
6823 } else
6824 px = curproxy;
6825
6826 srv = findserver(px, sname);
6827 if (!srv) {
6828 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6829 proxy_type_str(curproxy), curproxy->id,
6830 newsrv->id, sname);
6831 cfgerr++;
6832 goto next_srv;
6833 }
6834
Willy Tarreau32091232014-05-16 13:52:00 +02006835 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6836 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6837 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006838 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006839 "tracking as it does not have any check nor agent enabled.\n",
6840 proxy_type_str(curproxy), curproxy->id,
6841 newsrv->id, px->id, srv->id);
6842 cfgerr++;
6843 goto next_srv;
6844 }
6845
6846 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6847
6848 if (loop) {
6849 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6850 "belongs to a tracking chain looping back to %s/%s.\n",
6851 proxy_type_str(curproxy), curproxy->id,
6852 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006853 cfgerr++;
6854 goto next_srv;
6855 }
6856
6857 if (curproxy != px &&
6858 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6859 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6860 "tracking: disable-on-404 option inconsistency.\n",
6861 proxy_type_str(curproxy), curproxy->id,
6862 newsrv->id, px->id, srv->id);
6863 cfgerr++;
6864 goto next_srv;
6865 }
6866
6867 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006868 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006869 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006870 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006871 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006872 }
6873
6874 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006875 newsrv->tracknext = srv->trackers;
6876 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006877
6878 free(newsrv->trackit);
6879 newsrv->trackit = NULL;
6880 }
6881 next_srv:
6882 newsrv = newsrv->next;
6883 }
6884
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006885 /* We have to initialize the server lookup mechanism depending
6886 * on what LB algorithm was choosen.
6887 */
6888
6889 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6890 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6891 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006892 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6893 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6894 init_server_map(curproxy);
6895 } else {
6896 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6897 fwrr_init_server_groups(curproxy);
6898 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006899 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006900
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006901 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006902 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6903 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6904 fwlc_init_server_tree(curproxy);
6905 } else {
6906 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6907 fas_init_server_tree(curproxy);
6908 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006909 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006910
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006911 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006912 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6913 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6914 chash_init_server_tree(curproxy);
6915 } else {
6916 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6917 init_server_map(curproxy);
6918 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006919 break;
6920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006921
6922 if (curproxy->options & PR_O_LOGASAP)
6923 curproxy->to_log &= ~LW_BYTES;
6924
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006925 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006926 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006927 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6928 proxy_type_str(curproxy), curproxy->id);
6929 err_code |= ERR_WARN;
6930 }
6931
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006932 if (curproxy->mode != PR_MODE_HTTP) {
6933 int optnum;
6934
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006935 if (curproxy->uri_auth) {
6936 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6937 proxy_type_str(curproxy), curproxy->id);
6938 err_code |= ERR_WARN;
6939 curproxy->uri_auth = NULL;
6940 }
6941
Willy Tarreau87cf5142011-08-19 22:57:24 +02006942 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006943 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6944 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6945 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006946 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006947 }
6948
6949 if (curproxy->options & PR_O_ORGTO) {
6950 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6951 "originalto", proxy_type_str(curproxy), curproxy->id);
6952 err_code |= ERR_WARN;
6953 curproxy->options &= ~PR_O_ORGTO;
6954 }
6955
6956 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6957 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6958 (curproxy->cap & cfg_opts[optnum].cap) &&
6959 (curproxy->options & cfg_opts[optnum].val)) {
6960 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6961 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6962 err_code |= ERR_WARN;
6963 curproxy->options &= ~cfg_opts[optnum].val;
6964 }
6965 }
6966
6967 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6968 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6969 (curproxy->cap & cfg_opts2[optnum].cap) &&
6970 (curproxy->options2 & cfg_opts2[optnum].val)) {
6971 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6972 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6973 err_code |= ERR_WARN;
6974 curproxy->options2 &= ~cfg_opts2[optnum].val;
6975 }
6976 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006977
Pieter Baauwd551fb52013-05-08 22:49:23 +02006978#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006979 if (curproxy->conn_src.bind_hdr_occ) {
6980 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006981 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006982 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006983 err_code |= ERR_WARN;
6984 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006985#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006986 }
6987
Willy Tarreaubaaee002006-06-26 02:48:02 +02006988 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006989 * ensure that we're not cross-dressing a TCP server into HTTP.
6990 */
6991 newsrv = curproxy->srv;
6992 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006993 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006994 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6995 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006996 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006997 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006998
Willy Tarreau0cec3312011-10-31 13:49:26 +01006999 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7000 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7001 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7002 err_code |= ERR_WARN;
7003 }
7004
Willy Tarreauc93cd162014-05-13 15:54:22 +02007005 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007006 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7007 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7008 err_code |= ERR_WARN;
7009 }
7010
Pieter Baauwd551fb52013-05-08 22:49:23 +02007011#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007012 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7013 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007014 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 +01007015 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007016 err_code |= ERR_WARN;
7017 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007018#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007019 newsrv = newsrv->next;
7020 }
7021
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007022 /* check if we have a frontend with "tcp-request content" looking at L7
7023 * with no inspect-delay
7024 */
7025 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7026 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7027 if (trule->action == TCP_ACT_CAPTURE &&
7028 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7029 break;
7030 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7031 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7032 break;
7033 }
7034
7035 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7036 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7037 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7038 " This means that these rules will randomly find their contents. This can be fixed by"
7039 " setting the tcp-request inspect-delay.\n",
7040 proxy_type_str(curproxy), curproxy->id);
7041 err_code |= ERR_WARN;
7042 }
7043 }
7044
Willy Tarreauc1a21672009-08-16 22:37:44 +02007045 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007046 if (!curproxy->accept)
7047 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007048
Willy Tarreauc1a21672009-08-16 22:37:44 +02007049 if (curproxy->tcp_req.inspect_delay ||
7050 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007051 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007052
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007053 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007054 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007055 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007056 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007057
7058 /* both TCP and HTTP must check switching rules */
7059 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7060 }
7061
7062 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007063 if (curproxy->tcp_req.inspect_delay ||
7064 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7065 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7066
Emeric Brun97679e72010-09-23 17:56:44 +02007067 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7068 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7069
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007070 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007071 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007072 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007073 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007074
7075 /* If the backend does requires RDP cookie persistence, we have to
7076 * enable the corresponding analyser.
7077 */
7078 if (curproxy->options2 & PR_O2_RDPC_PRST)
7079 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7080 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007081 }
7082
7083 /***********************************************************/
7084 /* At this point, target names have already been resolved. */
7085 /***********************************************************/
7086
7087 /* Check multi-process mode compatibility */
7088
7089 if (global.nbproc > 1 && global.stats_fe) {
7090 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7091 unsigned long mask;
7092
7093 mask = nbits(global.nbproc);
7094 if (global.stats_fe->bind_proc)
7095 mask &= global.stats_fe->bind_proc;
7096
7097 if (bind_conf->bind_proc)
7098 mask &= bind_conf->bind_proc;
7099
7100 /* stop here if more than one process is used */
7101 if (popcount(mask) > 1)
7102 break;
7103 }
7104 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7105 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");
7106 }
7107 }
7108
7109 /* Make each frontend inherit bind-process from its listeners when not specified. */
7110 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7111 if (curproxy->bind_proc)
7112 continue;
7113
7114 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7115 unsigned long mask;
7116
7117 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7118 curproxy->bind_proc |= mask;
7119 }
7120
7121 if (!curproxy->bind_proc)
7122 curproxy->bind_proc = ~0UL;
7123 }
7124
7125 if (global.stats_fe) {
7126 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7127 unsigned long mask;
7128
7129 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7130 global.stats_fe->bind_proc |= mask;
7131 }
7132 if (!global.stats_fe->bind_proc)
7133 global.stats_fe->bind_proc = ~0UL;
7134 }
7135
Willy Tarreaub3228c82014-10-01 20:50:17 +02007136 /* propagate bindings from frontends to backends. Don't do it if there
7137 * are any fatal errors as we must not call it with unresolved proxies.
7138 */
7139 if (!cfgerr) {
7140 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7141 if (curproxy->cap & PR_CAP_FE)
7142 propagate_processes(curproxy, NULL);
7143 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007144 }
7145
7146 /* Bind each unbound backend to all processes when not specified. */
7147 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7148 if (curproxy->bind_proc)
7149 continue;
7150 curproxy->bind_proc = ~0UL;
7151 }
7152
7153 /*******************************************************/
7154 /* At this step, all proxies have a non-null bind_proc */
7155 /*******************************************************/
7156
7157 /* perform the final checks before creating tasks */
7158
7159 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7160 struct listener *listener;
7161 unsigned int next_id;
7162 int nbproc;
7163
7164 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007165
Emeric Brunc52962f2012-11-15 18:28:02 +01007166#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007167 /* Configure SSL for each bind line.
7168 * Note: if configuration fails at some point, the ->ctx member
7169 * remains NULL so that listeners can later detach.
7170 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007171 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007172 int alloc_ctx;
7173
Emeric Brunc52962f2012-11-15 18:28:02 +01007174 if (!bind_conf->is_ssl) {
7175 if (bind_conf->default_ctx) {
7176 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7177 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7178 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007179 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007180 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007181 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007182 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007183 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007184 cfgerr++;
7185 continue;
7186 }
7187
Emeric Brun8dc60392014-05-09 13:52:00 +02007188 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007189 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007190 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7191 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");
7192 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007193 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007194 cfgerr++;
7195 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007196 }
7197
Emeric Brunfc0421f2012-09-07 17:30:07 +02007198 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007199 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007200 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007201#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007202
Willy Tarreaue6b98942007-10-29 01:09:36 +01007203 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007204 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007205 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007206 if (!listener->luid) {
7207 /* listener ID not set, use automatic numbering with first
7208 * spare entry starting with next_luid.
7209 */
7210 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7211 listener->conf.id.key = listener->luid = next_id;
7212 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007213 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007214 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007215
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007216 /* enable separate counters */
7217 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7218 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007219 if (!listener->name)
7220 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007221 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007222
Willy Tarreaue6b98942007-10-29 01:09:36 +01007223 if (curproxy->options & PR_O_TCP_NOLING)
7224 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007225 if (!listener->maxconn)
7226 listener->maxconn = curproxy->maxconn;
7227 if (!listener->backlog)
7228 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007229 if (!listener->maxaccept)
7230 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7231
7232 /* we want to have an optimal behaviour on single process mode to
7233 * maximize the work at once, but in multi-process we want to keep
7234 * some fairness between processes, so we target half of the max
7235 * number of events to be balanced over all the processes the proxy
7236 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7237 * used to disable the limit.
7238 */
7239 if (listener->maxaccept > 0) {
7240 if (nbproc > 1)
7241 listener->maxaccept = (listener->maxaccept + 1) / 2;
7242 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7243 }
7244
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007245 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007246 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007247 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007248 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007249
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007250 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7251 listener->options |= LI_O_TCP_RULES;
7252
Willy Tarreaude3041d2010-05-31 10:56:17 +02007253 if (curproxy->mon_mask.s_addr)
7254 listener->options |= LI_O_CHK_MONNET;
7255
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007256 /* smart accept mode is automatic in HTTP mode */
7257 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007258 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007259 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7260 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007261 }
7262
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007263 /* Release unused SSL configs */
7264 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7265 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007266 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007267#ifdef USE_OPENSSL
7268 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007269 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007270 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007271 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007272 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007273#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007274 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007275
Willy Tarreau102df612014-05-07 23:56:38 +02007276 if (nbproc > 1) {
7277 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007278 int count, maxproc = 0;
7279
7280 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7281 count = popcount(bind_conf->bind_proc);
7282 if (count > maxproc)
7283 maxproc = count;
7284 }
7285 /* backends have 0, frontends have 1 or more */
7286 if (maxproc != 1)
7287 Warning("Proxy '%s': in multi-process mode, stats will be"
7288 " limited to process assigned to the current request.\n",
7289 curproxy->id);
7290
Willy Tarreau102df612014-05-07 23:56:38 +02007291 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7292 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7293 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007294 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007295 }
Willy Tarreau102df612014-05-07 23:56:38 +02007296 if (curproxy->appsession_name) {
7297 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7298 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007299 }
Willy Tarreau102df612014-05-07 23:56:38 +02007300 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7301 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7302 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007303 }
7304 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007305
7306 /* create the task associated with the proxy */
7307 curproxy->task = task_new();
7308 if (curproxy->task) {
7309 curproxy->task->context = curproxy;
7310 curproxy->task->process = manage_proxy;
7311 /* no need to queue, it will be done automatically if some
7312 * listener gets limited.
7313 */
7314 curproxy->task->expire = TICK_ETERNITY;
7315 } else {
7316 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7317 curproxy->id);
7318 cfgerr++;
7319 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007320 }
7321
Willy Tarreaufbb78422011-06-05 15:38:35 +02007322 /* automatically compute fullconn if not set. We must not do it in the
7323 * loop above because cross-references are not yet fully resolved.
7324 */
7325 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7326 /* If <fullconn> is not set, let's set it to 10% of the sum of
7327 * the possible incoming frontend's maxconns.
7328 */
7329 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7330 struct proxy *fe;
7331 int total = 0;
7332
7333 /* sum up the number of maxconns of frontends which
7334 * reference this backend at least once or which are
7335 * the same one ('listen').
7336 */
7337 for (fe = proxy; fe; fe = fe->next) {
7338 struct switching_rule *rule;
7339 struct hdr_exp *exp;
7340 int found = 0;
7341
7342 if (!(fe->cap & PR_CAP_FE))
7343 continue;
7344
7345 if (fe == curproxy) /* we're on a "listen" instance */
7346 found = 1;
7347
7348 if (fe->defbe.be == curproxy) /* "default_backend" */
7349 found = 1;
7350
7351 /* check if a "use_backend" rule matches */
7352 if (!found) {
7353 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007354 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007355 found = 1;
7356 break;
7357 }
7358 }
7359 }
7360
7361 /* check if a "reqsetbe" rule matches */
7362 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7363 if (exp->action == ACT_SETBE &&
7364 (struct proxy *)exp->replace == curproxy) {
7365 found = 1;
7366 break;
7367 }
7368 }
7369
7370 /* now we've checked all possible ways to reference a backend
7371 * from a frontend.
7372 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007373 if (!found)
7374 continue;
7375 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007376 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007377 /* we have the sum of the maxconns in <total>. We only
7378 * keep 10% of that sum to set the default fullconn, with
7379 * a hard minimum of 1 (to avoid a divide by zero).
7380 */
7381 curproxy->fullconn = (total + 9) / 10;
7382 if (!curproxy->fullconn)
7383 curproxy->fullconn = 1;
7384 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007385 }
7386
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007387 /*
7388 * Recount currently required checks.
7389 */
7390
7391 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7392 int optnum;
7393
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007394 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7395 if (curproxy->options & cfg_opts[optnum].val)
7396 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007397
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007398 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7399 if (curproxy->options2 & cfg_opts2[optnum].val)
7400 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007401 }
7402
Willy Tarreaucdb5e922015-05-01 19:12:05 +02007403 /* compute the required process bindings for the peers */
7404 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7405 if (curproxy->table.peers.p)
7406 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7407
Willy Tarreau122541c2011-09-07 21:24:49 +02007408 if (peers) {
7409 struct peers *curpeers = peers, **last;
7410 struct peer *p, *pb;
7411
7412 /* Remove all peers sections which don't have a valid listener.
7413 * This can happen when a peers section is never referenced and
7414 * does not contain a local peer.
7415 */
7416 last = &peers;
7417 while (*last) {
7418 curpeers = *last;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007419
7420 if (curpeers->state == PR_STSTOPPED) {
7421 /* the "disabled" keyword was present */
7422 if (curpeers->peers_fe)
7423 stop_proxy(curpeers->peers_fe);
7424 curpeers->peers_fe = NULL;
7425 }
7426 else if (!curpeers->peers_fe) {
7427 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7428 curpeers->id, localpeer);
7429 }
7430 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007431 last = &curpeers->next;
7432 continue;
7433 }
7434
Willy Tarreau34d05b02015-05-01 20:02:17 +02007435 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007436 p = curpeers->remote;
7437 while (p) {
7438 pb = p->next;
7439 free(p->id);
7440 free(p);
7441 p = pb;
7442 }
7443
7444 /* Destroy and unlink this curpeers section.
7445 * Note: curpeers is backed up into *last.
7446 */
7447 free(curpeers->id);
7448 curpeers = curpeers->next;
7449 free(*last);
7450 *last = curpeers;
7451 }
7452 }
7453
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007454 /* initialize stick-tables on backend capable proxies. This must not
7455 * be done earlier because the data size may be discovered while parsing
7456 * other proxies.
7457 */
7458 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7459 if (curproxy->state == PR_STSTOPPED)
7460 continue;
7461
7462 if (!stktable_init(&curproxy->table)) {
7463 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7464 cfgerr++;
7465 }
7466 }
7467
Willy Tarreau34eb6712011-10-24 18:15:04 +02007468 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007469 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007470 MEM_F_SHARED);
7471
Willy Tarreaubb925012009-07-23 13:36:36 +02007472 if (cfgerr > 0)
7473 err_code |= ERR_ALERT | ERR_FATAL;
7474 out:
7475 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007476}
7477
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007478/*
7479 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7480 * parsing sessions.
7481 */
7482void cfg_register_keywords(struct cfg_kw_list *kwl)
7483{
7484 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7485}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007486
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007487/*
7488 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7489 */
7490void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7491{
7492 LIST_DEL(&kwl->list);
7493 LIST_INIT(&kwl->list);
7494}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007495
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007496/* this function register new section in the haproxy configuration file.
7497 * <section_name> is the name of this new section and <section_parser>
7498 * is the called parser. If two section declaration have the same name,
7499 * only the first declared is used.
7500 */
7501int cfg_register_section(char *section_name,
7502 int (*section_parser)(const char *, int, char **, int))
7503{
7504 struct cfg_section *cs;
7505
7506 cs = calloc(1, sizeof(*cs));
7507 if (!cs) {
7508 Alert("register section '%s': out of memory.\n", section_name);
7509 return 0;
7510 }
7511
7512 cs->section_name = section_name;
7513 cs->section_parser = section_parser;
7514
7515 LIST_ADDQ(&sections, &cs->list);
7516
7517 return 1;
7518}
7519
Willy Tarreaubaaee002006-06-26 02:48:02 +02007520/*
7521 * Local variables:
7522 * c-indent-level: 8
7523 * c-basic-offset: 8
7524 * End:
7525 */