blob: 2519e84a8904b63b1e4cab5705fbc3d1175169cc [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
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 Tarreau9420b122013-12-15 18:58:25 +0100154 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
156 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
157 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
158 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
159 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100160#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100162#else
163 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100164#endif
165
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100167};
168
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100169/* proxy->options2 */
170static const struct cfg_opt cfg_opts2[] =
171{
172#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
174 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100176#else
177 { "splice-request", 0, 0, 0, 0 },
178 { "splice-response", 0, 0, 0, 0 },
179 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100180#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
182 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
183 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
184 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
185 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
186 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
187 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
189 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400190 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100191 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200192 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200193 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100194 { NULL, 0, 0, 0 }
195};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196
Willy Tarreau6daf3432008-01-22 16:44:08 +0100197static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
199int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100200int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200202/* List head of all known configuration keywords */
203static struct cfg_kw_list cfg_keywords = {
204 .list = LIST_HEAD_INIT(cfg_keywords.list)
205};
206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207/*
208 * converts <str> to a list of listeners which are dynamically allocated.
209 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
210 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
211 * - <port> is a numerical port from 1 to 65535 ;
212 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
213 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200214 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
215 * not NULL, it must be a valid pointer to either NULL or a freeable area that
216 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218int 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 +0200219{
220 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100221 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 int port, end;
223
224 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200225
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100227 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100228 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
230 str = next;
231 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100232 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 *next++ = 0;
234 }
235
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100236 ss2 = str2sa_range(str, &port, &end, err,
237 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
238 if (!ss2)
239 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100242 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port || !end) {
248 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
249 goto fail;
250 }
251
Emeric Bruned760922010-10-22 17:59:25 +0200252 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200253 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
256
257 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100262 else if (ss2->ss_family == AF_UNSPEC) {
263 socklen_t addr_len;
264
265 /* We want to attach to an already bound fd whose number
266 * is in the addr part of ss2 when cast to sockaddr_in.
267 * Note that by definition there is a single listener.
268 * We still have to determine the address family to
269 * register the correct protocol.
270 */
271 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
272 addr_len = sizeof(*ss2);
273 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
274 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
275 goto fail;
276 }
277
278 port = end = get_host_port(ss2);
279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100281 /* OK the address looks correct */
282 ss = *ss2;
283
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 for (; port <= end; port++) {
285 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100286 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200287 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
288 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
289 l->frontend = curproxy;
290 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291
Willy Tarreau40aa0702013-03-10 23:51:38 +0100292 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200294 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100295 l->state = LI_INIT;
296
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100297 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 tcpv4_add_listener(l);
300 }
Emeric Bruned760922010-10-22 17:59:25 +0200301 else if (ss.ss_family == AF_INET6) {
302 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
303 tcpv6_add_listener(l);
304 }
305 else {
Emeric Bruned760922010-10-22 17:59:25 +0200306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau61d18892009-03-31 10:49:21 +0200320/* Report a warning if a rule is placed after a 'block' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200325 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
Willy Tarreau5002f572014-04-23 01:32:02 +0200333/* Report a warning if a rule is placed after an 'http_request' rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
336int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
337{
338 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
Willy Tarreau61d18892009-03-31 10:49:21 +0200346/* Report a warning if a rule is placed after a reqrewrite rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (proxy->req_exp) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a reqadd rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100364 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a redirect rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a 'use_backend' rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
Willy Tarreauee445d92014-04-23 01:39:04 +0200398/* Report a warning if a rule is placed after a 'use-server' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
401int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
402{
403 if (!LIST_ISEMPTY(&proxy->server_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
Willy Tarreau61d18892009-03-31 10:49:21 +0200411/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreau5002f572014-04-23 01:32:02 +0200414 return warnif_rule_after_http_req(proxy, file, line, arg) ||
415 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200420}
421
422/* report a warning if an http-request rule is dangerously placed */
423int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
424{
Willy Tarreau61d18892009-03-31 10:49:21 +0200425 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
426 warnif_rule_after_reqadd(proxy, file, line, arg) ||
427 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200428 warnif_rule_after_use_backend(proxy, file, line, arg) ||
429 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200430}
431
432/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100433int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200434{
435 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
436 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200437 warnif_rule_after_use_backend(proxy, file, line, arg) ||
438 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200439}
440
441/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200445 warnif_rule_after_use_backend(proxy, file, line, arg) ||
446 warnif_rule_after_use_server(proxy, file, line, arg);
447}
448
449/* report a warning if a redirect rule is dangerously placed */
450int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
451{
452 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
453 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200454}
455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456/* Report it if a request ACL condition uses some keywords that are incompatible
457 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
458 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
459 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100460 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100461static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100462{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100463 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200464 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100465
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100466 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100467 return 0;
468
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100469 acl = acl_cond_conflicts(cond, where);
470 if (acl) {
471 if (acl->name && *acl->name)
472 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
473 file, line, acl->name, sample_ckp_names(where));
474 else
475 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 +0200476 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100477 return ERR_WARN;
478 }
479 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100480 return 0;
481
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100482 if (acl->name && *acl->name)
483 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200484 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100485 else
486 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200487 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100488 return ERR_WARN;
489}
490
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 * parse a line in a <global> section. Returns the error code, 0 if OK, or
493 * any combination of :
494 * - ERR_ABORT: must abort ASAP
495 * - ERR_FATAL: we can continue parsing but not start the service
496 * - ERR_WARN: a warning has been emitted
497 * - ERR_ALERT: an alert has been emitted
498 * Only the two first ones can stop processing, the two others are just
499 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200501int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502{
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200504 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505
506 if (!strcmp(args[0], "global")) { /* new section */
507 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200510 else if (!strcmp(args[0], "ca-base")) {
511#ifdef USE_OPENSSL
512 if (global.ca_base != NULL) {
513 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
514 err_code |= ERR_ALERT;
515 goto out;
516 }
517 if (*(args[1]) == 0) {
518 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
519 err_code |= ERR_ALERT | ERR_FATAL;
520 goto out;
521 }
522 global.ca_base = strdup(args[1]);
523#else
524 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
527#endif
528 }
529 else if (!strcmp(args[0], "crt-base")) {
530#ifdef USE_OPENSSL
531 if (global.crt_base != NULL) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT;
534 goto out;
535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
540 }
541 global.crt_base = strdup(args[1]);
542#else
543 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
546#endif
547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 else if (!strcmp(args[0], "daemon")) {
549 global.mode |= MODE_DAEMON;
550 }
551 else if (!strcmp(args[0], "debug")) {
552 global.mode |= MODE_DEBUG;
553 }
554 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100555 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200557 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100558 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100561 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200562 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100563 else if (!strcmp(args[0], "nosplice")) {
564 global.tune.options &= ~GTUNE_USE_SPLICE;
565 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200566 else if (!strcmp(args[0], "nogetaddrinfo")) {
567 global.tune.options &= ~GTUNE_USE_GAI;
568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 else if (!strcmp(args[0], "quiet")) {
570 global.mode |= MODE_QUIET;
571 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 else if (!strcmp(args[0], "tune.maxpollevents")) {
573 if (global.tune.maxpollevents != 0) {
574 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT;
576 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200577 }
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200582 }
583 global.tune.maxpollevents = atol(args[1]);
584 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 else if (!strcmp(args[0], "tune.maxaccept")) {
586 if (global.tune.maxaccept != 0) {
587 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT;
589 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100590 }
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100595 }
596 global.tune.maxaccept = atol(args[1]);
597 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200598 else if (!strcmp(args[0], "tune.chksize")) {
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.tune.chksize = atol(args[1]);
605 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200606#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200607 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
608 global.tune.sslprivatecache = 1;
609 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100610 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.sslcachesize = atol(args[1]);
617 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100618 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
619 unsigned int ssllifetime;
620 const char *res;
621
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627
628 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
629 if (res) {
630 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
631 file, linenum, *res, args[0]);
632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
634 }
635
636 global.tune.ssllifetime = ssllifetime;
637 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100638 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
639 if (*(args[1]) == 0) {
640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.ssl_max_record = atol(args[1]);
645 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200646 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 global.tune.ssl_default_dh_param = atol(args[1]);
653 if (global.tune.ssl_default_dh_param < 1024) {
654 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200659#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200660 else if (!strcmp(args[0], "tune.bufsize")) {
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.bufsize = atol(args[1]);
667 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
668 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100669 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100670 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200671 }
672 else if (!strcmp(args[0], "tune.maxrewrite")) {
673 if (*(args[1]) == 0) {
674 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
677 }
678 global.tune.maxrewrite = atol(args[1]);
679 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
680 global.tune.maxrewrite = global.tune.bufsize / 2;
681 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100682 else if (!strcmp(args[0], "tune.idletimer")) {
683 unsigned int idle;
684 const char *res;
685
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691
692 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
693 if (res) {
694 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
695 file, linenum, *res, args[0]);
696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
698 }
699
700 if (idle > 65535) {
701 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.idle_timer = idle;
706 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100707 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
708 if (global.tune.client_rcvbuf != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT;
711 goto out;
712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718 global.tune.client_rcvbuf = atol(args[1]);
719 }
720 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
721 if (global.tune.server_rcvbuf != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT;
724 goto out;
725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.server_rcvbuf = atol(args[1]);
732 }
733 else if (!strcmp(args[0], "tune.sndbuf.client")) {
734 if (global.tune.client_sndbuf != 0) {
735 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
736 err_code |= ERR_ALERT;
737 goto out;
738 }
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.client_sndbuf = atol(args[1]);
745 }
746 else if (!strcmp(args[0], "tune.sndbuf.server")) {
747 if (global.tune.server_sndbuf != 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.server_sndbuf = atol(args[1]);
758 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200759 else if (!strcmp(args[0], "tune.pipesize")) {
760 if (*(args[1]) == 0) {
761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765 global.tune.pipesize = atol(args[1]);
766 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100767 else if (!strcmp(args[0], "tune.http.cookielen")) {
768 if (*(args[1]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 global.tune.cookie_len = atol(args[1]) + 1;
774 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200775 else if (!strcmp(args[0], "tune.http.maxhdr")) {
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781 global.tune.max_http_hdr = atol(args[1]);
782 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100783 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
784#ifdef USE_ZLIB
785 if (*args[1]) {
786 global.tune.zlibmemlevel = atoi(args[1]);
787 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
788 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793 } else {
794 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
795 file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799#else
800 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803#endif
804 }
805 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
806#ifdef USE_ZLIB
807 if (*args[1]) {
808 global.tune.zlibwindowsize = atoi(args[1]);
809 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
810 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
811 file, linenum, args[0]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815 } else {
816 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
817 file, linenum, args[0]);
818 err_code |= ERR_ALERT | ERR_FATAL;
819 goto out;
820 }
821#else
822 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825#endif
826 }
William Lallemandf3747832012-11-09 12:33:10 +0100827 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
828 if (*args[1]) {
829 global.tune.comp_maxlevel = atoi(args[1]);
830 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
831 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
832 file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836 } else {
837 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
838 file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 else if (!strcmp(args[0], "uid")) {
844 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200845 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200846 err_code |= ERR_ALERT;
847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 }
849 if (*(args[1]) == 0) {
850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 }
854 global.uid = atol(args[1]);
855 }
856 else if (!strcmp(args[0], "gid")) {
857 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200858 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200859 err_code |= ERR_ALERT;
860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 }
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 }
867 global.gid = atol(args[1]);
868 }
Simon Horman98637e52014-06-20 12:30:16 +0900869 else if (!strcmp(args[0], "external-check")) {
870 global.external_check = 1;
871 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200872 /* user/group name handling */
873 else if (!strcmp(args[0], "user")) {
874 struct passwd *ha_user;
875 if (global.uid != 0) {
876 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT;
878 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200879 }
880 errno = 0;
881 ha_user = getpwnam(args[1]);
882 if (ha_user != NULL) {
883 global.uid = (int)ha_user->pw_uid;
884 }
885 else {
886 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 +0200887 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200888 }
889 }
890 else if (!strcmp(args[0], "group")) {
891 struct group *ha_group;
892 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200893 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 err_code |= ERR_ALERT;
895 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200896 }
897 errno = 0;
898 ha_group = getgrnam(args[1]);
899 if (ha_group != NULL) {
900 global.gid = (int)ha_group->gr_gid;
901 }
902 else {
903 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 +0200904 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200905 }
906 }
907 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 }
914 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100915 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
916 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
917 file, linenum, args[0], LONGBITS, global.nbproc);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 }
922 else if (!strcmp(args[0], "maxconn")) {
923 if (global.maxconn != 0) {
924 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT;
926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 if (*(args[1]) == 0) {
929 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT | ERR_FATAL;
931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 global.maxconn = atol(args[1]);
934#ifdef SYSTEM_MAXCONN
935 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
936 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);
937 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200938 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 }
940#endif /* SYSTEM_MAXCONN */
941 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200942 else if (!strcmp(args[0], "maxsslconn")) {
943#ifdef USE_OPENSSL
944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949 global.maxsslconn = atol(args[1]);
950#else
Emeric Brun0914df82012-10-02 18:45:42 +0200951 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200954#endif
955 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100956 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
957#ifdef USE_OPENSSL
958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
962 }
963 free(global.listen_default_ciphers);
964 global.listen_default_ciphers = strdup(args[1]);
965#else
966 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
967 err_code |= ERR_ALERT | ERR_FATAL;
968 goto out;
969#endif
970 }
971 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
972#ifdef USE_OPENSSL
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978 free(global.connect_default_ciphers);
979 global.connect_default_ciphers = strdup(args[1]);
980#else
981 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984#endif
985 }
Emeric Brun850efd52014-01-29 12:24:34 +0100986 else if (!strcmp(args[0], "ssl-server-verify")) {
987 if (*(args[1]) == 0) {
988 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
991 }
992 if (strcmp(args[1],"none") == 0)
993 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
994 else if (strcmp(args[1],"required") == 0)
995 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
996 else {
997 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001002 else if (!strcmp(args[0], "maxconnrate")) {
1003 if (global.cps_lim != 0) {
1004 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1005 err_code |= ERR_ALERT;
1006 goto out;
1007 }
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 global.cps_lim = atol(args[1]);
1014 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001015 else if (!strcmp(args[0], "maxsessrate")) {
1016 if (global.sps_lim != 0) {
1017 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT;
1019 goto out;
1020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 global.sps_lim = atol(args[1]);
1027 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001028 else if (!strcmp(args[0], "maxsslrate")) {
1029 if (global.ssl_lim != 0) {
1030 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1031 err_code |= ERR_ALERT;
1032 goto out;
1033 }
1034 if (*(args[1]) == 0) {
1035 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 global.ssl_lim = atol(args[1]);
1040 }
William Lallemandd85f9172012-11-09 17:05:39 +01001041 else if (!strcmp(args[0], "maxcomprate")) {
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047 global.comp_rate_lim = atoi(args[1]) * 1024;
1048 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001049 else if (!strcmp(args[0], "maxpipes")) {
1050 if (global.maxpipes != 0) {
1051 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT;
1053 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001054 }
1055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001059 }
1060 global.maxpipes = atol(args[1]);
1061 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001062 else if (!strcmp(args[0], "maxzlibmem")) {
1063 if (*(args[1]) == 0) {
1064 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1065 err_code |= ERR_ALERT | ERR_FATAL;
1066 goto out;
1067 }
William Lallemande3a7d992012-11-20 11:25:20 +01001068 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001069 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001070 else if (!strcmp(args[0], "maxcompcpuusage")) {
1071 if (*(args[1]) == 0) {
1072 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001077 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001078 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
1081 }
1082}
1083
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 else if (!strcmp(args[0], "ulimit-n")) {
1085 if (global.rlimit_nofile != 0) {
1086 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001087 err_code |= ERR_ALERT;
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
1090 if (*(args[1]) == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 }
1095 global.rlimit_nofile = atol(args[1]);
1096 }
1097 else if (!strcmp(args[0], "chroot")) {
1098 if (global.chroot != NULL) {
1099 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001100 err_code |= ERR_ALERT;
1101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 }
1103 if (*(args[1]) == 0) {
1104 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001105 err_code |= ERR_ALERT | ERR_FATAL;
1106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 }
1108 global.chroot = strdup(args[1]);
1109 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001110 else if (!strcmp(args[0], "description")) {
1111 int i, len=0;
1112 char *d;
1113
1114 if (!*args[1]) {
1115 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1116 file, linenum, args[0]);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto out;
1119 }
1120
Willy Tarreau348acfe2014-04-14 15:00:39 +02001121 for (i = 1; *args[i]; i++)
1122 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001123
1124 if (global.desc)
1125 free(global.desc);
1126
1127 global.desc = d = (char *)calloc(1, len);
1128
Willy Tarreau348acfe2014-04-14 15:00:39 +02001129 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1130 for (i = 2; *args[i]; i++)
1131 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001132 }
1133 else if (!strcmp(args[0], "node")) {
1134 int i;
1135 char c;
1136
1137 for (i=0; args[1][i]; i++) {
1138 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001139 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1140 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001141 break;
1142 }
1143
1144 if (!i || args[1][i]) {
1145 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1146 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1147 file, linenum, args[0]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
1150 }
1151
1152 if (global.node)
1153 free(global.node);
1154
1155 global.node = strdup(args[1]);
1156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 else if (!strcmp(args[0], "pidfile")) {
1158 if (global.pidfile != NULL) {
1159 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001160 err_code |= ERR_ALERT;
1161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 }
1163 if (*(args[1]) == 0) {
1164 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 }
1168 global.pidfile = strdup(args[1]);
1169 }
Emeric Bruned760922010-10-22 17:59:25 +02001170 else if (!strcmp(args[0], "unix-bind")) {
1171 int cur_arg = 1;
1172 while (*(args[cur_arg])) {
1173 if (!strcmp(args[cur_arg], "prefix")) {
1174 if (global.unix_bind.prefix != NULL) {
1175 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1176 err_code |= ERR_ALERT;
1177 cur_arg += 2;
1178 continue;
1179 }
1180
1181 if (*(args[cur_arg+1]) == 0) {
1182 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1183 err_code |= ERR_ALERT | ERR_FATAL;
1184 goto out;
1185 }
1186 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1187 cur_arg += 2;
1188 continue;
1189 }
1190
1191 if (!strcmp(args[cur_arg], "mode")) {
1192
1193 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1194 cur_arg += 2;
1195 continue;
1196 }
1197
1198 if (!strcmp(args[cur_arg], "uid")) {
1199
1200 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1201 cur_arg += 2;
1202 continue;
1203 }
1204
1205 if (!strcmp(args[cur_arg], "gid")) {
1206
1207 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1208 cur_arg += 2;
1209 continue;
1210 }
1211
1212 if (!strcmp(args[cur_arg], "user")) {
1213 struct passwd *user;
1214
1215 user = getpwnam(args[cur_arg + 1]);
1216 if (!user) {
1217 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1218 file, linenum, args[0], args[cur_arg + 1 ]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222
1223 global.unix_bind.ux.uid = user->pw_uid;
1224 cur_arg += 2;
1225 continue;
1226 }
1227
1228 if (!strcmp(args[cur_arg], "group")) {
1229 struct group *group;
1230
1231 group = getgrnam(args[cur_arg + 1]);
1232 if (!group) {
1233 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1234 file, linenum, args[0], args[cur_arg + 1 ]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 global.unix_bind.ux.gid = group->gr_gid;
1240 cur_arg += 2;
1241 continue;
1242 }
1243
Willy Tarreaub48f9582011-09-05 01:17:06 +02001244 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001245 file, linenum, args[0]);
1246 err_code |= ERR_ALERT | ERR_FATAL;
1247 goto out;
1248 }
1249 }
William Lallemand0f99e342011-10-12 17:50:54 +02001250 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1251 /* delete previous herited or defined syslog servers */
1252 struct logsrv *back;
1253 struct logsrv *tmp;
1254
1255 if (*(args[1]) != 0) {
1256 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260
1261 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1262 LIST_DEL(&tmp->list);
1263 free(tmp);
1264 }
1265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001267 struct sockaddr_storage *sk;
1268 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001269 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001270 int arg = 0;
1271 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001272
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 if (*(args[1]) == 0 || *(args[2]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 }
William Lallemand0f99e342011-10-12 17:50:54 +02001278
1279 logsrv = calloc(1, sizeof(struct logsrv));
1280
Willy Tarreau18324f52014-06-27 18:10:07 +02001281 /* just after the address, a length may be specified */
1282 if (strcmp(args[arg+2], "len") == 0) {
1283 len = atoi(args[arg+3]);
1284 if (len < 80 || len > 65535) {
1285 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1286 file, linenum, args[arg+3]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 logsrv->maxlen = len;
1291
1292 /* skip these two args */
1293 arg += 2;
1294 }
1295 else
1296 logsrv->maxlen = MAX_SYSLOG_LEN;
1297
1298 if (logsrv->maxlen > global.max_syslog_len) {
1299 global.max_syslog_len = logsrv->maxlen;
1300 logline = realloc(logline, global.max_syslog_len + 1);
1301 }
1302
1303 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001304 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001305 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001306 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001307 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 }
1309
William Lallemand0f99e342011-10-12 17:50:54 +02001310 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001311 if (*(args[arg+3])) {
1312 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001313 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001314 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001316 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317 }
1318 }
1319
William Lallemand0f99e342011-10-12 17:50:54 +02001320 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001321 if (*(args[arg+4])) {
1322 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001323 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001324 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001325 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001326 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001327 }
1328 }
1329
Willy Tarreau902636f2013-03-10 19:44:48 +01001330 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001331 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001332 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001333 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001334 free(logsrv);
1335 goto out;
1336 }
1337 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001338
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001339 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001340 if (port1 != port2) {
1341 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1342 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001343 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001344 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001345 goto out;
1346 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001347
William Lallemand0f99e342011-10-12 17:50:54 +02001348 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001349 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001350 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352
William Lallemand0f99e342011-10-12 17:50:54 +02001353 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001354 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001355 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1356 char *name;
1357 int len;
1358
1359 if (global.log_send_hostname != NULL) {
1360 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1361 err_code |= ERR_ALERT;
1362 goto out;
1363 }
1364
1365 if (*(args[1]))
1366 name = args[1];
1367 else
1368 name = hostname;
1369
1370 len = strlen(name);
1371
1372 /* We'll add a space after the name to respect the log format */
1373 free(global.log_send_hostname);
1374 global.log_send_hostname = malloc(len + 2);
1375 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1376 }
Kevinm48936af2010-12-22 16:08:21 +00001377 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1378 if (*(args[1]) == 0) {
1379 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
1382 }
1383 free(global.log_tag);
1384 global.log_tag = strdup(args[1]);
1385 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001386 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1387 if (global.spread_checks != 0) {
1388 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001389 err_code |= ERR_ALERT;
1390 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001391 }
1392 if (*(args[1]) == 0) {
1393 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001394 err_code |= ERR_ALERT | ERR_FATAL;
1395 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001396 }
1397 global.spread_checks = atol(args[1]);
1398 if (global.spread_checks < 0 || global.spread_checks > 50) {
1399 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001400 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001403 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1404 const char *err;
1405 unsigned int val;
1406
1407
1408 if (*(args[1]) == 0) {
1409 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
1412 }
1413
1414 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1415 if (err) {
1416 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 }
1419 global.max_spread_checks = val;
1420 if (global.max_spread_checks < 0) {
1421 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1422 err_code |= ERR_ALERT | ERR_FATAL;
1423 }
1424 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001425 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1426#ifdef USE_CPU_AFFINITY
1427 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001428 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001429 unsigned long cpus = 0;
1430
1431 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001432 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001433 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001434 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001435 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001436 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001437 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001438 proc = atol(args[1]);
1439 if (proc >= 1 && proc <= LONGBITS)
1440 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001441 }
1442
1443 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001444 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",
1445 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449
1450 cur_arg = 2;
1451 while (*args[cur_arg]) {
1452 unsigned int low, high;
1453
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001454 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001455 char *dash = strchr(args[cur_arg], '-');
1456
1457 low = high = str2uic(args[cur_arg]);
1458 if (dash)
1459 high = str2uic(dash + 1);
1460
1461 if (high < low) {
1462 unsigned int swap = low;
1463 low = high;
1464 high = swap;
1465 }
1466
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001467 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001468 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001469 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001470 err_code |= ERR_ALERT | ERR_FATAL;
1471 goto out;
1472 }
1473
1474 while (low <= high)
1475 cpus |= 1UL << low++;
1476 }
1477 else {
1478 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1479 file, linenum, args[0], args[cur_arg]);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto out;
1482 }
1483 cur_arg++;
1484 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001485 for (i = 0; i < LONGBITS; i++)
1486 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001487 global.cpu_map[i] = cpus;
1488#else
1489 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492#endif
1493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001495 struct cfg_kw_list *kwl;
1496 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001497 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001498
1499 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1500 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1501 if (kwl->kw[index].section != CFG_GLOBAL)
1502 continue;
1503 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001504 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001505 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001506 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001508 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001509 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001510 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001511 err_code |= ERR_WARN;
1512 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001513 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001514 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001515 }
1516 }
1517 }
1518
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001520 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001522
Willy Tarreau058e9072009-07-20 09:30:05 +02001523 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001524 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001525 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526}
1527
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001528void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001530 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 defproxy.mode = PR_MODE_TCP;
1532 defproxy.state = PR_STNEW;
1533 defproxy.maxconn = cfg_maxpconn;
1534 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001535
Simon Horman66183002013-02-23 10:16:43 +09001536 defproxy.defsrv.check.inter = DEF_CHKINTR;
1537 defproxy.defsrv.check.fastinter = 0;
1538 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001539 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1540 defproxy.defsrv.agent.fastinter = 0;
1541 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001542 defproxy.defsrv.check.rise = DEF_RISETIME;
1543 defproxy.defsrv.check.fall = DEF_FALLTIME;
1544 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1545 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001546 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001547 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001548 defproxy.defsrv.maxqueue = 0;
1549 defproxy.defsrv.minconn = 0;
1550 defproxy.defsrv.maxconn = 0;
1551 defproxy.defsrv.slowstart = 0;
1552 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1553 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1554 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555}
1556
Willy Tarreauade5ec42010-01-28 19:33:49 +01001557
Willy Tarreau63af98d2014-05-18 08:11:41 +02001558/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1559 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1560 * ERR_FATAL in case of error.
1561 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001562static int create_cond_regex_rule(const char *file, int line,
1563 struct proxy *px, int dir, int action, int flags,
1564 const char *cmd, const char *reg, const char *repl,
1565 const char **cond_start)
1566{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001567 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001568 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001569 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001570 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001571 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001572 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001573 int cs;
1574 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001575
1576 if (px == &defproxy) {
1577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001578 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001579 goto err;
1580 }
1581
1582 if (*reg == 0) {
1583 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001584 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001585 goto err;
1586 }
1587
1588 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001589 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001590
Willy Tarreau5321c422010-01-28 20:35:13 +01001591 if (cond_start &&
1592 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001593 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1594 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1595 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001596 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001597 goto err;
1598 }
1599 }
1600 else if (cond_start && **cond_start) {
1601 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1602 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001603 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001604 goto err;
1605 }
1606
Willy Tarreau63af98d2014-05-18 08:11:41 +02001607 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001608 (dir == SMP_OPT_DIR_REQ) ?
1609 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1610 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1611 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001612
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001613 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614 if (!preg) {
1615 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001616 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001617 goto err;
1618 }
1619
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001620 cs = !(flags & REG_ICASE);
1621 cap = !(flags & REG_NOSUB);
1622 error = NULL;
1623 if (!regex_comp(reg, preg, cs, cap, &error)) {
1624 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1625 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001626 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001627 goto err;
1628 }
1629
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001630 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001631 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001632 if (repl && err) {
1633 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1634 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001635 ret_code |= ERR_ALERT | ERR_FATAL;
1636 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001637 }
1638
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001639 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001640 ret_code |= ERR_WARN;
1641
1642 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001643
Willy Tarreau63af98d2014-05-18 08:11:41 +02001644 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001645 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001646 err:
1647 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001648 free(errmsg);
1649 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001650}
1651
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001653 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001654 * Returns the error code, 0 if OK, or any combination of :
1655 * - ERR_ABORT: must abort ASAP
1656 * - ERR_FATAL: we can continue parsing but not start the service
1657 * - ERR_WARN: a warning has been emitted
1658 * - ERR_ALERT: an alert has been emitted
1659 * Only the two first ones can stop processing, the two others are just
1660 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001662int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1663{
1664 static struct peers *curpeers = NULL;
1665 struct peer *newpeer = NULL;
1666 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001667 struct bind_conf *bind_conf;
1668 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001669 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001670 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001671
1672 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001673 if (!*args[1]) {
1674 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001675 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001676 goto out;
1677 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001678
1679 err = invalid_char(args[1]);
1680 if (err) {
1681 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1682 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001683 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001684 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001685 }
1686
1687 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1688 /*
1689 * If there are two proxies with the same name only following
1690 * combinations are allowed:
1691 */
1692 if (strcmp(curpeers->id, args[1]) == 0) {
1693 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1694 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1695 err_code |= ERR_WARN;
1696 }
1697 }
1698
1699 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1700 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1701 err_code |= ERR_ALERT | ERR_ABORT;
1702 goto out;
1703 }
1704
1705 curpeers->next = peers;
1706 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001707 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001708 curpeers->conf.line = linenum;
1709 curpeers->last_change = now.tv_sec;
1710 curpeers->id = strdup(args[1]);
1711 }
1712 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001713 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001714 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001715 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001716
1717 if (!*args[2]) {
1718 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1719 file, linenum, args[0]);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723
1724 err = invalid_char(args[1]);
1725 if (err) {
1726 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1727 file, linenum, *err, args[1]);
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
1731
1732 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1733 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1734 err_code |= ERR_ALERT | ERR_ABORT;
1735 goto out;
1736 }
1737
1738 /* the peers are linked backwards first */
1739 curpeers->count++;
1740 newpeer->next = curpeers->remote;
1741 curpeers->remote = newpeer;
1742 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001743 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001744 newpeer->conf.line = linenum;
1745
1746 newpeer->last_change = now.tv_sec;
1747 newpeer->id = strdup(args[1]);
1748
Willy Tarreau902636f2013-03-10 19:44:48 +01001749 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001750 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001751 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001754 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001755
1756 proto = protocol_by_family(sk->ss_family);
1757 if (!proto || !proto->connect) {
1758 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1759 file, linenum, args[0], args[1]);
1760 err_code |= ERR_ALERT | ERR_FATAL;
1761 goto out;
1762 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001763
1764 if (port1 != port2) {
1765 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1766 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
Willy Tarreau2aa38802013-02-20 19:20:59 +01001771 if (!port1) {
1772 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1773 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
1776 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001777
Emeric Brun32da3c42010-09-23 18:39:19 +02001778 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001779 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001780 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001781 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001782
Emeric Brun32da3c42010-09-23 18:39:19 +02001783 if (strcmp(newpeer->id, localpeer) == 0) {
1784 /* Current is local peer, it define a frontend */
1785 newpeer->local = 1;
1786
1787 if (!curpeers->peers_fe) {
1788 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1789 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1790 err_code |= ERR_ALERT | ERR_ABORT;
1791 goto out;
1792 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001793
Willy Tarreau237250c2011-07-29 01:49:03 +02001794 init_new_proxy(curpeers->peers_fe);
1795 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001796
1797 curpeers->peers_fe->last_change = now.tv_sec;
1798 curpeers->peers_fe->id = strdup(args[1]);
1799 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001800 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001801 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1802 curpeers->peers_fe->timeout.connect = 5000;
1803 curpeers->peers_fe->accept = peer_accept;
1804 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001805 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1806 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001807
1808 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1809
Willy Tarreau902636f2013-03-10 19:44:48 +01001810 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1811 if (errmsg && *errmsg) {
1812 indent_msg(&errmsg, 2);
1813 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001814 }
1815 else
1816 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1817 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001818 err_code |= ERR_FATAL;
1819 goto out;
1820 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001821
1822 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001823 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001824 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1825 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1826 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1827 l->accept = session_accept;
1828 l->handler = process_session;
1829 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1830 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1831 global.maxsock += l->maxconn;
1832 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001833 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001834 else {
1835 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1836 file, linenum, args[0], args[1],
1837 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1838 err_code |= ERR_FATAL;
1839 goto out;
1840 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001841 }
1842 } /* neither "peer" nor "peers" */
1843 else if (*args[0] != 0) {
1844 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
1847 }
1848
1849out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001850 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001851 return err_code;
1852}
1853
Willy Tarreau3842f002009-06-14 11:39:52 +02001854int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855{
1856 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001857 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001858 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001859 int rc;
1860 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001861 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001862 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001863 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001864 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001865 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866
Willy Tarreau977b8e42006-12-29 14:19:17 +01001867 if (!strcmp(args[0], "listen"))
1868 rc = PR_CAP_LISTEN;
1869 else if (!strcmp(args[0], "frontend"))
1870 rc = PR_CAP_FE | PR_CAP_RS;
1871 else if (!strcmp(args[0], "backend"))
1872 rc = PR_CAP_BE | PR_CAP_RS;
1873 else if (!strcmp(args[0], "ruleset"))
1874 rc = PR_CAP_RS;
1875 else
1876 rc = PR_CAP_NONE;
1877
1878 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001879 struct ebpt_node *node;
1880
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 if (!*args[1]) {
1882 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1883 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001885 err_code |= ERR_ALERT | ERR_ABORT;
1886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001888
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001889 err = invalid_char(args[1]);
1890 if (err) {
1891 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1892 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001893 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001894 }
1895
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001896 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1897 curproxy = container_of(node, struct proxy, conf.by_name);
1898
1899 if (strcmp(curproxy->id, args[1]) != 0)
1900 break;
1901
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001902 /*
1903 * If there are two proxies with the same name only following
1904 * combinations are allowed:
1905 *
1906 * listen backend frontend ruleset
1907 * listen - - - -
1908 * backend - - OK -
1909 * frontend - OK - -
1910 * ruleset - - - -
1911 */
1912
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001913 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1914 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001915 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1916 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1917 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001918 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001919 }
1920 }
1921
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1923 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001924 err_code |= ERR_ALERT | ERR_ABORT;
1925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001927
Willy Tarreau97cb7802010-01-03 20:23:58 +01001928 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 curproxy->next = proxy;
1930 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001931 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1932 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001933 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001936 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937
1938 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001940 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001941
Willy Tarreau4348fad2012-09-20 16:48:07 +02001942 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1943
Willy Tarreau902636f2013-03-10 19:44:48 +01001944 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1945 if (errmsg && *errmsg) {
1946 indent_msg(&errmsg, 2);
1947 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001948 }
1949 else
1950 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1951 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_FATAL;
1953 goto out;
1954 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001955
Willy Tarreau4348fad2012-09-20 16:48:07 +02001956 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001957 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 }
1960
1961 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001962 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001963 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001964
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001967 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001968 curproxy->no_options = defproxy.no_options;
1969 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001970 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001971 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001972 curproxy->except_net = defproxy.except_net;
1973 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001974 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001975 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001977 if (defproxy.fwdfor_hdr_len) {
1978 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1979 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1980 }
1981
Willy Tarreaub86db342009-11-30 11:50:16 +01001982 if (defproxy.orgto_hdr_len) {
1983 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1984 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1985 }
1986
Mark Lamourinec2247f02012-01-04 13:02:01 -05001987 if (defproxy.server_id_hdr_len) {
1988 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1989 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1990 }
1991
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992 if (curproxy->cap & PR_CAP_FE) {
1993 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001994 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001995 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996
1997 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001998 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1999 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002000
2001 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003
Willy Tarreau977b8e42006-12-29 14:19:17 +01002004 if (curproxy->cap & PR_CAP_BE) {
2005 curproxy->fullconn = defproxy.fullconn;
2006 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002007 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002009 if (defproxy.check_req) {
2010 curproxy->check_req = calloc(1, defproxy.check_len);
2011 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2012 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002013 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002015 if (defproxy.expect_str) {
2016 curproxy->expect_str = strdup(defproxy.expect_str);
2017 if (defproxy.expect_regex) {
2018 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002019 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2020 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002021 }
2022 }
2023
Willy Tarreau67402132012-05-31 20:40:20 +02002024 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002025 if (defproxy.cookie_name)
2026 curproxy->cookie_name = strdup(defproxy.cookie_name);
2027 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002028 if (defproxy.cookie_domain)
2029 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002030
Willy Tarreau31936852010-10-06 16:59:56 +02002031 if (defproxy.cookie_maxidle)
2032 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2033
2034 if (defproxy.cookie_maxlife)
2035 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2036
Emeric Brun647caf12009-06-30 17:57:00 +02002037 if (defproxy.rdp_cookie_name)
2038 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2039 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2040
Willy Tarreau01732802007-11-01 22:48:15 +01002041 if (defproxy.url_param_name)
2042 curproxy->url_param_name = strdup(defproxy.url_param_name);
2043 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002044
Benoitaffb4812009-03-25 13:02:10 +01002045 if (defproxy.hh_name)
2046 curproxy->hh_name = strdup(defproxy.hh_name);
2047 curproxy->hh_len = defproxy.hh_len;
2048 curproxy->hh_match_domain = defproxy.hh_match_domain;
2049
Willy Tarreauef9a3602012-12-08 22:29:20 +01002050 if (defproxy.conn_src.iface_name)
2051 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2052 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002053 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002054#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002055 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002056#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002058
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002059 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002060 if (defproxy.capture_name)
2061 curproxy->capture_name = strdup(defproxy.capture_name);
2062 curproxy->capture_namelen = defproxy.capture_namelen;
2063 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065
Willy Tarreau977b8e42006-12-29 14:19:17 +01002066 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002067 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002068 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002069 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002070 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002071 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002072 curproxy->mon_net = defproxy.mon_net;
2073 curproxy->mon_mask = defproxy.mon_mask;
2074 if (defproxy.monitor_uri)
2075 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2076 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002077 if (defproxy.defbe.name)
2078 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002079
2080 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002081 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2082 if (curproxy->conf.logformat_string &&
2083 curproxy->conf.logformat_string != default_http_log_format &&
2084 curproxy->conf.logformat_string != default_tcp_log_format &&
2085 curproxy->conf.logformat_string != clf_http_log_format)
2086 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2087
2088 if (defproxy.conf.lfs_file) {
2089 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2090 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2091 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002092 }
2093
2094 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002095 curproxy->timeout.connect = defproxy.timeout.connect;
2096 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002097 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002098 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002099 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002100 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002101 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002102 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002103 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002104 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 }
2106
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002108 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002109
2110 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002111 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002112 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002113 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002114 LIST_INIT(&node->list);
2115 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2116 }
2117
Willy Tarreau62a61232013-04-12 18:13:46 +02002118 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2119 if (curproxy->conf.uniqueid_format_string)
2120 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2121
2122 if (defproxy.conf.uif_file) {
2123 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2124 curproxy->conf.uif_line = defproxy.conf.uif_line;
2125 }
William Lallemanda73203e2012-03-12 12:48:57 +01002126
2127 /* copy default header unique id */
2128 if (defproxy.header_unique_id)
2129 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2130
William Lallemand82fe75c2012-10-23 10:25:10 +02002131 /* default compression options */
2132 if (defproxy.comp != NULL) {
2133 curproxy->comp = calloc(1, sizeof(struct comp));
2134 curproxy->comp->algos = defproxy.comp->algos;
2135 curproxy->comp->types = defproxy.comp->types;
2136 }
2137
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002139 curproxy->conf.used_listener_id = EB_ROOT;
2140 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002141
Simon Horman98637e52014-06-20 12:30:16 +09002142 if (defproxy.check_path)
2143 curproxy->check_path = strdup(defproxy.check_path);
2144 if (defproxy.check_command)
2145 curproxy->check_command = strdup(defproxy.check_command);
2146
Willy Tarreau93893792009-07-23 13:19:11 +02002147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 }
2149 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2150 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002151 /* FIXME-20070101: we should do this too at the end of the
2152 * config parsing to free all default values.
2153 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002154 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002155 free(defproxy.check_command);
2156 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002157 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002158 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002159 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002160 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002161 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002162 free(defproxy.capture_name);
2163 free(defproxy.monitor_uri);
2164 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002165 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002166 free(defproxy.fwdfor_hdr_name);
2167 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002168 free(defproxy.orgto_hdr_name);
2169 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002170 free(defproxy.server_id_hdr_name);
2171 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002172 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002173 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002174 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002175 free(defproxy.expect_regex);
2176 defproxy.expect_regex = NULL;
2177 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002178
Willy Tarreau62a61232013-04-12 18:13:46 +02002179 if (defproxy.conf.logformat_string != default_http_log_format &&
2180 defproxy.conf.logformat_string != default_tcp_log_format &&
2181 defproxy.conf.logformat_string != clf_http_log_format)
2182 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002183
Willy Tarreau62a61232013-04-12 18:13:46 +02002184 free(defproxy.conf.uniqueid_format_string);
2185 free(defproxy.conf.lfs_file);
2186 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002187
Willy Tarreaua534fea2008-08-03 12:19:50 +02002188 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002189 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002190
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 /* we cannot free uri_auth because it might already be used */
2192 init_default_instance();
2193 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002194 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2195 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002196 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 }
2199 else if (curproxy == NULL) {
2200 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002204
2205 /* update the current file and line being parsed */
2206 curproxy->conf.args.file = curproxy->conf.file;
2207 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208
2209 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002210 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2211 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2212 if (err_code & ERR_FATAL)
2213 goto out;
2214 }
2215 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002216 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002217 int cur_arg;
2218
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 if (curproxy == &defproxy) {
2220 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002223 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002225 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226
Willy Tarreau24709282013-03-10 21:32:12 +01002227 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002228 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002233
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002234 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002235
2236 /* use default settings for unix sockets */
2237 bind_conf->ux.uid = global.unix_bind.ux.uid;
2238 bind_conf->ux.gid = global.unix_bind.ux.gid;
2239 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002240
2241 /* NOTE: the following line might create several listeners if there
2242 * are comma-separated IPs or port ranges. So all further processing
2243 * will have to be applied to all listeners created after last_listen.
2244 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002245 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2246 if (errmsg && *errmsg) {
2247 indent_msg(&errmsg, 2);
2248 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002249 }
2250 else
2251 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2252 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
2255 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002256
Willy Tarreau4348fad2012-09-20 16:48:07 +02002257 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2258 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002259 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002260 }
2261
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002262 cur_arg = 2;
2263 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002264 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002265 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002266 char *err;
2267
Willy Tarreau26982662012-09-12 23:17:10 +02002268 kw = bind_find_kw(args[cur_arg]);
2269 if (kw) {
2270 char *err = NULL;
2271 int code;
2272
2273 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002274 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2275 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002276 cur_arg += 1 + kw->skip ;
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280
Willy Tarreau4348fad2012-09-20 16:48:07 +02002281 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002282 err_code |= code;
2283
2284 if (code) {
2285 if (err && *err) {
2286 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002287 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002288 }
2289 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002290 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2291 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002292 if (code & ERR_FATAL) {
2293 free(err);
2294 cur_arg += 1 + kw->skip;
2295 goto out;
2296 }
2297 }
2298 free(err);
2299 cur_arg += 1 + kw->skip;
2300 continue;
2301 }
2302
Willy Tarreau8638f482012-09-18 18:01:17 +02002303 err = NULL;
2304 if (!bind_dumped) {
2305 bind_dump_kws(&err);
2306 indent_msg(&err, 4);
2307 bind_dumped = 1;
2308 }
2309
2310 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2311 file, linenum, args[0], args[1], args[cur_arg],
2312 err ? " Registered keywords :" : "", err ? err : "");
2313 free(err);
2314
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002317 }
Willy Tarreau93893792009-07-23 13:19:11 +02002318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
2320 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002321 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 /* flush useless bits */
2331 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002334 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002335 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002337
Willy Tarreau1c47f852006-07-09 08:22:27 +02002338 if (!*args[1]) {
2339 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002343 }
2344
Willy Tarreaua534fea2008-08-03 12:19:50 +02002345 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002346 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002347 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002348 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002349 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2350
Willy Tarreau93893792009-07-23 13:19:11 +02002351 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2354 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2355 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2356 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2357 else {
2358 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002363 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002364 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002365
2366 if (curproxy == &defproxy) {
2367 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2368 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002371 }
2372
2373 if (!*args[1]) {
2374 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2375 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002378 }
2379
2380 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002381 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002382
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002383 if (curproxy->uuid <= 0) {
2384 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002385 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002388 }
2389
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002390 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2391 if (node) {
2392 struct proxy *target = container_of(node, struct proxy, conf.id);
2393 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2394 file, linenum, proxy_type_str(curproxy), curproxy->id,
2395 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
2398 }
2399 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002400 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002401 else if (!strcmp(args[0], "description")) {
2402 int i, len=0;
2403 char *d;
2404
Cyril Bonté99ed3272010-01-24 23:29:44 +01002405 if (curproxy == &defproxy) {
2406 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2407 file, linenum, args[0]);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002412 if (!*args[1]) {
2413 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2414 file, linenum, args[0]);
2415 return -1;
2416 }
2417
Willy Tarreau348acfe2014-04-14 15:00:39 +02002418 for (i = 1; *args[i]; i++)
2419 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002420
2421 d = (char *)calloc(1, len);
2422 curproxy->desc = d;
2423
Willy Tarreau348acfe2014-04-14 15:00:39 +02002424 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2425 for (i = 2; *args[i]; i++)
2426 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002427
2428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2430 curproxy->state = PR_STSTOPPED;
2431 }
2432 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2433 curproxy->state = PR_STNEW;
2434 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002435 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2436 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002437 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002438
2439 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002440 unsigned int low, high;
2441
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002442 if (strcmp(args[cur_arg], "all") == 0) {
2443 set = 0;
2444 break;
2445 }
2446 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002447 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002448 }
2449 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002450 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002451 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002452 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002453 char *dash = strchr(args[cur_arg], '-');
2454
2455 low = high = str2uic(args[cur_arg]);
2456 if (dash)
2457 high = str2uic(dash + 1);
2458
2459 if (high < low) {
2460 unsigned int swap = low;
2461 low = high;
2462 high = swap;
2463 }
2464
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002465 if (low < 1 || high > LONGBITS) {
2466 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2467 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002470 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002471 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002472 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002473 }
2474 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002475 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2476 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002479 }
2480 cur_arg++;
2481 }
2482 curproxy->bind_proc = set;
2483 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002484 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002485 if (curproxy == &defproxy) {
2486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002489 }
2490
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002491 err = invalid_char(args[1]);
2492 if (err) {
2493 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2494 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002496 }
2497
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002498 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002499 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2500 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002503 }
2504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2506 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507
Willy Tarreau977b8e42006-12-29 14:19:17 +01002508 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002510
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 if (*(args[1]) == 0) {
2512 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2513 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002517
Willy Tarreau67402132012-05-31 20:40:20 +02002518 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002519 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002520 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002521 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 curproxy->cookie_name = strdup(args[1]);
2523 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002524
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 cur_arg = 2;
2526 while (*(args[cur_arg])) {
2527 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002528 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 }
2530 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002531 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
2533 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002534 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 }
2536 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002537 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 }
2539 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002540 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002542 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002543 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002544 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002546 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002548 else if (!strcmp(args[cur_arg], "httponly")) {
2549 curproxy->ck_opts |= PR_CK_HTTPONLY;
2550 }
2551 else if (!strcmp(args[cur_arg], "secure")) {
2552 curproxy->ck_opts |= PR_CK_SECURE;
2553 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002554 else if (!strcmp(args[cur_arg], "domain")) {
2555 if (!*args[cur_arg + 1]) {
2556 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2557 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002560 }
2561
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002562 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002563 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002564 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2565 " dots nor does not start with a dot."
2566 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002567 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002568 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002569 }
2570
2571 err = invalid_domainchar(args[cur_arg + 1]);
2572 if (err) {
2573 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2574 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002577 }
2578
Willy Tarreau68a897b2009-12-03 23:28:34 +01002579 if (!curproxy->cookie_domain) {
2580 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2581 } else {
2582 /* one domain was already specified, add another one by
2583 * building the string which will be returned along with
2584 * the cookie.
2585 */
2586 char *new_ptr;
2587 int new_len = strlen(curproxy->cookie_domain) +
2588 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2589 new_ptr = malloc(new_len);
2590 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2591 free(curproxy->cookie_domain);
2592 curproxy->cookie_domain = new_ptr;
2593 }
Willy Tarreau31936852010-10-06 16:59:56 +02002594 cur_arg++;
2595 }
2596 else if (!strcmp(args[cur_arg], "maxidle")) {
2597 unsigned int maxidle;
2598 const char *res;
2599
2600 if (!*args[cur_arg + 1]) {
2601 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2602 file, linenum, args[cur_arg]);
2603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
2605 }
2606
2607 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2608 if (res) {
2609 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2610 file, linenum, *res, args[cur_arg]);
2611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
2613 }
2614 curproxy->cookie_maxidle = maxidle;
2615 cur_arg++;
2616 }
2617 else if (!strcmp(args[cur_arg], "maxlife")) {
2618 unsigned int maxlife;
2619 const char *res;
2620
2621 if (!*args[cur_arg + 1]) {
2622 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2623 file, linenum, args[cur_arg]);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627
2628 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2629 if (res) {
2630 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2631 file, linenum, *res, args[cur_arg]);
2632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
2634 }
2635 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002636 cur_arg++;
2637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002639 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 +02002640 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
2644 cur_arg++;
2645 }
Willy Tarreau67402132012-05-31 20:40:20 +02002646 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2648 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 }
2651
Willy Tarreau67402132012-05-31 20:40:20 +02002652 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2654 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002657
Willy Tarreau67402132012-05-31 20:40:20 +02002658 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002659 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2660 file, linenum);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002664 else if (!strcmp(args[0], "external-check")) {
2665 if (*(args[1]) == 0) {
2666 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2667 file, linenum, args[0]);
2668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671
2672 if (!strcmp(args[1], "command")) {
2673 if (*(args[1]) == 0) {
2674 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2675 file, linenum, args[1]);
2676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
2678 }
2679 free(curproxy->check_command);
2680 curproxy->check_command = strdup(args[2]);
2681 }
2682 else if (!strcmp(args[1], "path")) {
2683 if (*(args[1]) == 0) {
2684 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2685 file, linenum, args[1]);
2686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
2689 free(curproxy->check_path);
2690 curproxy->check_path = strdup(args[2]);
2691 }
2692 else {
2693 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2694 file, linenum, args[1]);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002699 else if (!strcmp(args[0], "persist")) { /* persist */
2700 if (*(args[1]) == 0) {
2701 Alert("parsing [%s:%d] : missing persist method.\n",
2702 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002705 }
2706
2707 if (!strncmp(args[1], "rdp-cookie", 10)) {
2708 curproxy->options2 |= PR_O2_RDPC_PRST;
2709
Emeric Brunb982a3d2010-01-04 15:45:53 +01002710 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002711 const char *beg, *end;
2712
2713 beg = args[1] + 11;
2714 end = strchr(beg, ')');
2715
2716 if (!end || end == beg) {
2717 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2718 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002721 }
2722
2723 free(curproxy->rdp_cookie_name);
2724 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2725 curproxy->rdp_cookie_len = end-beg;
2726 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002727 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002728 free(curproxy->rdp_cookie_name);
2729 curproxy->rdp_cookie_name = strdup("msts");
2730 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2731 }
2732 else { /* syntax */
2733 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2734 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002737 }
2738 }
2739 else {
2740 Alert("parsing [%s:%d] : unknown persist method.\n",
2741 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002744 }
2745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002747 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002749 if (curproxy == &defproxy) {
2750 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
2753 }
2754
Willy Tarreau977b8e42006-12-29 14:19:17 +01002755 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002757
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002759 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002765 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 curproxy->appsession_name = strdup(args[1]);
2767 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2768 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002769 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2770 if (err) {
2771 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2772 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002775 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002776 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002777
Willy Tarreau51041c72007-09-09 21:56:53 +02002778 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2779 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_ABORT;
2781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002783
2784 cur_arg = 6;
2785 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002786 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2787 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002788 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002789 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002790 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002791 } else if (!strcmp(args[cur_arg], "prefix")) {
2792 curproxy->options2 |= PR_O2_AS_PFX;
2793 } else if (!strcmp(args[cur_arg], "mode")) {
2794 if (!*args[cur_arg + 1]) {
2795 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2796 file, linenum, args[0], args[cur_arg]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
2801 cur_arg++;
2802 if (!strcmp(args[cur_arg], "query-string")) {
2803 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2804 curproxy->options2 |= PR_O2_AS_M_QS;
2805 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2806 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2807 curproxy->options2 |= PR_O2_AS_M_PP;
2808 } else {
2809 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
2812 }
2813 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002814 cur_arg++;
2815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002816 } /* Url App Session */
2817 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002818 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002820
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002822 if (curproxy == &defproxy) {
2823 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
2826 }
2827
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 if (*(args[4]) == 0) {
2829 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2830 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002833 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002834 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 curproxy->capture_name = strdup(args[2]);
2836 curproxy->capture_namelen = strlen(curproxy->capture_name);
2837 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 curproxy->to_log |= LW_COOKIE;
2839 }
2840 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2841 struct cap_hdr *hdr;
2842
2843 if (curproxy == &defproxy) {
2844 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 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 }
2848
2849 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2850 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2851 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 }
2855
2856 hdr = calloc(sizeof(struct cap_hdr), 1);
2857 hdr->next = curproxy->req_cap;
2858 hdr->name = strdup(args[3]);
2859 hdr->namelen = strlen(args[3]);
2860 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002861 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 hdr->index = curproxy->nb_req_cap++;
2863 curproxy->req_cap = hdr;
2864 curproxy->to_log |= LW_REQHDR;
2865 }
2866 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2867 struct cap_hdr *hdr;
2868
2869 if (curproxy == &defproxy) {
2870 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 +02002871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 }
2874
2875 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2876 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2877 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 }
2881 hdr = calloc(sizeof(struct cap_hdr), 1);
2882 hdr->next = curproxy->rsp_cap;
2883 hdr->name = strdup(args[3]);
2884 hdr->namelen = strlen(args[3]);
2885 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002886 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 hdr->index = curproxy->nb_rsp_cap++;
2888 curproxy->rsp_cap = hdr;
2889 curproxy->to_log |= LW_RSPHDR;
2890 }
2891 else {
2892 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2893 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
2897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002901
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 if (*(args[1]) == 0) {
2903 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2904 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 }
2908 curproxy->conn_retries = atol(args[1]);
2909 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002910 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002911 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002912
2913 if (curproxy == &defproxy) {
2914 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
2917 }
2918
Willy Tarreau20b0de52012-12-24 15:45:22 +01002919 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2920 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2921 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2922 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002923 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002924 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2925 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 +01002926 file, linenum, args[0]);
2927 err_code |= ERR_WARN;
2928 }
2929
Willy Tarreauff011f22011-01-06 17:51:27 +01002930 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002931
Willy Tarreauff011f22011-01-06 17:51:27 +01002932 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002933 err_code |= ERR_ALERT | ERR_ABORT;
2934 goto out;
2935 }
2936
Willy Tarreau5002f572014-04-23 01:32:02 +02002937 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002938 err_code |= warnif_cond_conflicts(rule->cond,
2939 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2940 file, linenum);
2941
Willy Tarreauff011f22011-01-06 17:51:27 +01002942 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002943 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002944 else if (!strcmp(args[0], "http-response")) { /* response access control */
2945 struct http_res_rule *rule;
2946
2947 if (curproxy == &defproxy) {
2948 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
2953 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2954 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2955 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2956 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2957 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2958 file, linenum, args[0]);
2959 err_code |= ERR_WARN;
2960 }
2961
2962 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2963
2964 if (!rule) {
2965 err_code |= ERR_ALERT | ERR_ABORT;
2966 goto out;
2967 }
2968
2969 err_code |= warnif_cond_conflicts(rule->cond,
2970 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2971 file, linenum);
2972
2973 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2974 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002975 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2976 /* set the header name and length into the proxy structure */
2977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2978 err_code |= ERR_WARN;
2979
2980 if (!*args[1]) {
2981 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2982 file, linenum, args[0]);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986
2987 /* set the desired header name */
2988 free(curproxy->server_id_hdr_name);
2989 curproxy->server_id_hdr_name = strdup(args[1]);
2990 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2991 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002992 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002993 struct http_req_rule *rule;
2994
Willy Tarreaub099aca2008-10-12 17:26:37 +02002995 if (curproxy == &defproxy) {
2996 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002999 }
3000
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003001 /* emulate "block" using "http-request block". Since these rules are supposed to
3002 * be processed before all http-request rules, we put them into their own list
3003 * and will insert them at the end.
3004 */
3005 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3006 if (!rule) {
3007 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003008 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003009 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003010 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3011 err_code |= warnif_cond_conflicts(rule->cond,
3012 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3013 file, linenum);
3014 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003015
3016 if (!already_warned(WARN_BLOCK_DEPRECATED))
3017 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]);
3018
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003019 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003020 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003021 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003022
Cyril Bonté99ed3272010-01-24 23:29:44 +01003023 if (curproxy == &defproxy) {
3024 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027 }
3028
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003029 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003030 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3031 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003034 }
3035
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003036 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003037 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003038 err_code |= warnif_cond_conflicts(rule->cond,
3039 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3040 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003041 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003042 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003043 struct switching_rule *rule;
3044
Willy Tarreaub099aca2008-10-12 17:26:37 +02003045 if (curproxy == &defproxy) {
3046 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003049 }
3050
Willy Tarreau55ea7572007-06-17 19:56:27 +02003051 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003053
3054 if (*(args[1]) == 0) {
3055 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003058 }
3059
Willy Tarreauf51658d2014-04-23 01:21:56 +02003060 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3061 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3062 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3063 file, linenum, errmsg);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003067
Willy Tarreauf51658d2014-04-23 01:21:56 +02003068 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003069 }
3070
3071 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3072 rule->cond = cond;
3073 rule->be.name = strdup(args[1]);
3074 LIST_INIT(&rule->list);
3075 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3076 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003077 else if (strcmp(args[0], "use-server") == 0) {
3078 struct server_rule *rule;
3079
3080 if (curproxy == &defproxy) {
3081 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
3085
3086 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3087 err_code |= ERR_WARN;
3088
3089 if (*(args[1]) == 0) {
3090 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
3095 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3096 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3097 file, linenum, args[0]);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003102 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3103 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3104 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003109 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003110
3111 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3112 rule->cond = cond;
3113 rule->srv.name = strdup(args[1]);
3114 LIST_INIT(&rule->list);
3115 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3116 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3117 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003118 else if ((!strcmp(args[0], "force-persist")) ||
3119 (!strcmp(args[0], "ignore-persist"))) {
3120 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003121
3122 if (curproxy == &defproxy) {
3123 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127
3128 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3129 err_code |= ERR_WARN;
3130
Willy Tarreauef6494c2010-01-28 17:12:36 +01003131 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003132 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3133 file, linenum, args[0]);
3134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
3136 }
3137
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003138 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3139 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3140 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
3143 }
3144
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003145 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3146 * where force-persist is applied.
3147 */
3148 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003149
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003150 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003151 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003152 if (!strcmp(args[0], "force-persist")) {
3153 rule->type = PERSIST_TYPE_FORCE;
3154 } else {
3155 rule->type = PERSIST_TYPE_IGNORE;
3156 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003157 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003158 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003159 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003160 else if (!strcmp(args[0], "stick-table")) {
3161 int myidx = 1;
3162
Emeric Brun32da3c42010-09-23 18:39:19 +02003163 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003164 curproxy->table.type = (unsigned int)-1;
3165 while (*args[myidx]) {
3166 const char *err;
3167
3168 if (strcmp(args[myidx], "size") == 0) {
3169 myidx++;
3170 if (!*(args[myidx])) {
3171 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3172 file, linenum, args[myidx-1]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3177 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3178 file, linenum, *err, args[myidx-1]);
3179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
3181 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003182 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003183 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003184 else if (strcmp(args[myidx], "peers") == 0) {
3185 myidx++;
Godbach50523162013-12-11 19:48:57 +08003186 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003187 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3188 file, linenum, args[myidx-1]);
3189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Godbach50523162013-12-11 19:48:57 +08003191 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003192 curproxy->table.peers.name = strdup(args[myidx++]);
3193 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003194 else if (strcmp(args[myidx], "expire") == 0) {
3195 myidx++;
3196 if (!*(args[myidx])) {
3197 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3198 file, linenum, args[myidx-1]);
3199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
3201 }
3202 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3203 if (err) {
3204 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3205 file, linenum, *err, args[myidx-1]);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
3209 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003210 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003211 }
3212 else if (strcmp(args[myidx], "nopurge") == 0) {
3213 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003214 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003215 }
3216 else if (strcmp(args[myidx], "type") == 0) {
3217 myidx++;
3218 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3219 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3220 file, linenum, args[myidx]);
3221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
3223 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003224 /* myidx already points to next arg */
3225 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003226 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003227 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003228 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003229
3230 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003231 nw = args[myidx];
3232 while (*nw) {
3233 /* the "store" keyword supports a comma-separated list */
3234 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003235 sa = NULL; /* store arg */
3236 while (*nw && *nw != ',') {
3237 if (*nw == '(') {
3238 *nw = 0;
3239 sa = ++nw;
3240 while (*nw != ')') {
3241 if (!*nw) {
3242 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3243 file, linenum, args[0], cw);
3244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
3246 }
3247 nw++;
3248 }
3249 *nw = '\0';
3250 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003251 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003252 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003253 if (*nw)
3254 *nw++ = '\0';
3255 type = stktable_get_data_type(cw);
3256 if (type < 0) {
3257 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3258 file, linenum, args[0], cw);
3259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
3261 }
Willy Tarreauac782882010-06-20 10:41:54 +02003262
3263 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3264 switch (err) {
3265 case PE_NONE: break;
3266 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003267 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3268 file, linenum, args[0], cw);
3269 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003270 break;
3271
3272 case PE_ARG_MISSING:
3273 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3274 file, linenum, args[0], cw);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
3277
3278 case PE_ARG_NOT_USED:
3279 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3280 file, linenum, args[0], cw);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283
3284 default:
3285 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3286 file, linenum, args[0], cw);
3287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003289 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003290 }
3291 myidx++;
3292 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003293 else {
3294 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3295 file, linenum, args[myidx]);
3296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003298 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003299 }
3300
3301 if (!curproxy->table.size) {
3302 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3303 file, linenum);
3304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
3306 }
3307
3308 if (curproxy->table.type == (unsigned int)-1) {
3309 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3310 file, linenum);
3311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
3313 }
3314 }
3315 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003316 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003317 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003318 int myidx = 0;
3319 const char *name = NULL;
3320 int flags;
3321
3322 if (curproxy == &defproxy) {
3323 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326 }
3327
3328 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3329 err_code |= ERR_WARN;
3330 goto out;
3331 }
3332
3333 myidx++;
3334 if ((strcmp(args[myidx], "store") == 0) ||
3335 (strcmp(args[myidx], "store-request") == 0)) {
3336 myidx++;
3337 flags = STK_IS_STORE;
3338 }
3339 else if (strcmp(args[myidx], "store-response") == 0) {
3340 myidx++;
3341 flags = STK_IS_STORE | STK_ON_RSP;
3342 }
3343 else if (strcmp(args[myidx], "match") == 0) {
3344 myidx++;
3345 flags = STK_IS_MATCH;
3346 }
3347 else if (strcmp(args[myidx], "on") == 0) {
3348 myidx++;
3349 flags = STK_IS_MATCH | STK_IS_STORE;
3350 }
3351 else {
3352 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
3357 if (*(args[myidx]) == 0) {
3358 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
3361 }
3362
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003363 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003364 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003365 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003366 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
3369 }
3370
3371 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003372 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3373 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3374 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003375 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003376 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003377 goto out;
3378 }
3379 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003380 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3381 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3382 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003383 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003384 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003385 goto out;
3386 }
3387 }
3388
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003389 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003390 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003391
Emeric Brunb982a3d2010-01-04 15:45:53 +01003392 if (strcmp(args[myidx], "table") == 0) {
3393 myidx++;
3394 name = args[myidx++];
3395 }
3396
Willy Tarreauef6494c2010-01-28 17:12:36 +01003397 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003398 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3399 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3400 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003401 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003402 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003403 goto out;
3404 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003405 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003406 else if (*(args[myidx])) {
3407 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3408 file, linenum, args[0], args[myidx]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003410 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003411 goto out;
3412 }
Emeric Brun97679e72010-09-23 17:56:44 +02003413 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003414 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003415 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003416 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003417
Emeric Brunb982a3d2010-01-04 15:45:53 +01003418 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3419 rule->cond = cond;
3420 rule->expr = expr;
3421 rule->flags = flags;
3422 rule->table.name = name ? strdup(name) : NULL;
3423 LIST_INIT(&rule->list);
3424 if (flags & STK_ON_RSP)
3425 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3426 else
3427 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 else if (!strcmp(args[0], "stats")) {
3430 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3431 curproxy->uri_auth = NULL; /* we must detach from the default config */
3432
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003433 if (!*args[1]) {
3434 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003435 } else if (!strcmp(args[1], "admin")) {
3436 struct stats_admin_rule *rule;
3437
3438 if (curproxy == &defproxy) {
3439 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
3443
3444 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3445 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3446 err_code |= ERR_ALERT | ERR_ABORT;
3447 goto out;
3448 }
3449
3450 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3451 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3452 file, linenum, args[0], args[1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003456 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3457 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3458 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
3462
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003463 err_code |= warnif_cond_conflicts(cond,
3464 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3465 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003466
3467 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3468 rule->cond = cond;
3469 LIST_INIT(&rule->list);
3470 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471 } else if (!strcmp(args[1], "uri")) {
3472 if (*(args[2]) == 0) {
3473 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_ABORT;
3479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 }
3481 } else if (!strcmp(args[1], "realm")) {
3482 if (*(args[2]) == 0) {
3483 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3487 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003488 err_code |= ERR_ALERT | ERR_ABORT;
3489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003491 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003492 unsigned interval;
3493
3494 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3495 if (err) {
3496 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3497 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003500 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3501 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_ABORT;
3503 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003504 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003505 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003506 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003507
3508 if (curproxy == &defproxy) {
3509 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513
3514 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3515 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3516 err_code |= ERR_ALERT | ERR_ABORT;
3517 goto out;
3518 }
3519
Willy Tarreauff011f22011-01-06 17:51:27 +01003520 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3521 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003522 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3523 file, linenum, args[0]);
3524 err_code |= ERR_WARN;
3525 }
3526
Willy Tarreauff011f22011-01-06 17:51:27 +01003527 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003528
Willy Tarreauff011f22011-01-06 17:51:27 +01003529 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003530 err_code |= ERR_ALERT | ERR_ABORT;
3531 goto out;
3532 }
3533
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003534 err_code |= warnif_cond_conflicts(rule->cond,
3535 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3536 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003537 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003538
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 } else if (!strcmp(args[1], "auth")) {
3540 if (*(args[2]) == 0) {
3541 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3545 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_ABORT;
3547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 }
3549 } else if (!strcmp(args[1], "scope")) {
3550 if (*(args[2]) == 0) {
3551 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3555 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_ABORT;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
3559 } else if (!strcmp(args[1], "enable")) {
3560 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3561 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_ALERT | ERR_ABORT;
3563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003565 } else if (!strcmp(args[1], "hide-version")) {
3566 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3567 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_ABORT;
3569 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003570 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003571 } else if (!strcmp(args[1], "show-legends")) {
3572 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3573 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3574 err_code |= ERR_ALERT | ERR_ABORT;
3575 goto out;
3576 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003577 } else if (!strcmp(args[1], "show-node")) {
3578
3579 if (*args[2]) {
3580 int i;
3581 char c;
3582
3583 for (i=0; args[2][i]; i++) {
3584 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003585 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3586 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003587 break;
3588 }
3589
3590 if (!i || args[2][i]) {
3591 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3592 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3593 file, linenum, args[0], args[1]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597 }
3598
3599 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3600 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3601 err_code |= ERR_ALERT | ERR_ABORT;
3602 goto out;
3603 }
3604 } else if (!strcmp(args[1], "show-desc")) {
3605 char *desc = NULL;
3606
3607 if (*args[2]) {
3608 int i, len=0;
3609 char *d;
3610
Willy Tarreau348acfe2014-04-14 15:00:39 +02003611 for (i = 2; *args[i]; i++)
3612 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003613
3614 desc = d = (char *)calloc(1, len);
3615
Willy Tarreau348acfe2014-04-14 15:00:39 +02003616 d += snprintf(d, desc + len - d, "%s", args[2]);
3617 for (i = 3; *args[i]; i++)
3618 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003619 }
3620
3621 if (!*args[2] && !global.desc)
3622 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3623 file, linenum, args[1]);
3624 else {
3625 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3626 free(desc);
3627 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3628 err_code |= ERR_ALERT | ERR_ABORT;
3629 goto out;
3630 }
3631 free(desc);
3632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003634stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003635 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 +01003636 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 }
3640 }
3641 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003642 int optnum;
3643
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003644 if (*(args[1]) == '\0') {
3645 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3646 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003650
3651 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3652 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003653 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3654 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3655 file, linenum, cfg_opts[optnum].name);
3656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
3658 }
Willy Tarreau93893792009-07-23 13:19:11 +02003659 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3660 err_code |= ERR_WARN;
3661 goto out;
3662 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003663
Willy Tarreau3842f002009-06-14 11:39:52 +02003664 curproxy->no_options &= ~cfg_opts[optnum].val;
3665 curproxy->options &= ~cfg_opts[optnum].val;
3666
3667 switch (kwm) {
3668 case KWM_STD:
3669 curproxy->options |= cfg_opts[optnum].val;
3670 break;
3671 case KWM_NO:
3672 curproxy->no_options |= cfg_opts[optnum].val;
3673 break;
3674 case KWM_DEF: /* already cleared */
3675 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003676 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003677
Willy Tarreau93893792009-07-23 13:19:11 +02003678 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003679 }
3680 }
3681
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003682 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3683 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003684 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3685 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3686 file, linenum, cfg_opts2[optnum].name);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
Willy Tarreau93893792009-07-23 13:19:11 +02003690 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3691 err_code |= ERR_WARN;
3692 goto out;
3693 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003694
Willy Tarreau3842f002009-06-14 11:39:52 +02003695 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3696 curproxy->options2 &= ~cfg_opts2[optnum].val;
3697
3698 switch (kwm) {
3699 case KWM_STD:
3700 curproxy->options2 |= cfg_opts2[optnum].val;
3701 break;
3702 case KWM_NO:
3703 curproxy->no_options2 |= cfg_opts2[optnum].val;
3704 break;
3705 case KWM_DEF: /* already cleared */
3706 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003707 }
Willy Tarreau93893792009-07-23 13:19:11 +02003708 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003709 }
3710 }
3711
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003712 /* HTTP options override each other. They can be cancelled using
3713 * "no option xxx" which only switches to default mode if the mode
3714 * was this one (useful for cancelling options set in defaults
3715 * sections).
3716 */
3717 if (strcmp(args[1], "httpclose") == 0) {
3718 if (kwm == KWM_STD) {
3719 curproxy->options &= ~PR_O_HTTP_MODE;
3720 curproxy->options |= PR_O_HTTP_PCL;
3721 goto out;
3722 }
3723 else if (kwm == KWM_NO) {
3724 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3725 curproxy->options &= ~PR_O_HTTP_MODE;
3726 goto out;
3727 }
3728 }
3729 else if (strcmp(args[1], "forceclose") == 0) {
3730 if (kwm == KWM_STD) {
3731 curproxy->options &= ~PR_O_HTTP_MODE;
3732 curproxy->options |= PR_O_HTTP_FCL;
3733 goto out;
3734 }
3735 else if (kwm == KWM_NO) {
3736 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3737 curproxy->options &= ~PR_O_HTTP_MODE;
3738 goto out;
3739 }
3740 }
3741 else if (strcmp(args[1], "http-server-close") == 0) {
3742 if (kwm == KWM_STD) {
3743 curproxy->options &= ~PR_O_HTTP_MODE;
3744 curproxy->options |= PR_O_HTTP_SCL;
3745 goto out;
3746 }
3747 else if (kwm == KWM_NO) {
3748 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3749 curproxy->options &= ~PR_O_HTTP_MODE;
3750 goto out;
3751 }
3752 }
3753 else if (strcmp(args[1], "http-keep-alive") == 0) {
3754 if (kwm == KWM_STD) {
3755 curproxy->options &= ~PR_O_HTTP_MODE;
3756 curproxy->options |= PR_O_HTTP_KAL;
3757 goto out;
3758 }
3759 else if (kwm == KWM_NO) {
3760 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3761 curproxy->options &= ~PR_O_HTTP_MODE;
3762 goto out;
3763 }
3764 }
3765 else if (strcmp(args[1], "http-tunnel") == 0) {
3766 if (kwm == KWM_STD) {
3767 curproxy->options &= ~PR_O_HTTP_MODE;
3768 curproxy->options |= PR_O_HTTP_TUN;
3769 goto out;
3770 }
3771 else if (kwm == KWM_NO) {
3772 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3773 curproxy->options &= ~PR_O_HTTP_MODE;
3774 goto out;
3775 }
3776 }
3777
Willy Tarreau3842f002009-06-14 11:39:52 +02003778 if (kwm != KWM_STD) {
3779 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003780 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003783 }
3784
Emeric Brun3a058f32009-06-30 18:26:00 +02003785 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003786 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003788 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003789 if (*(args[2]) != '\0') {
3790 if (!strcmp(args[2], "clf")) {
3791 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003792 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003793 } else {
3794 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003797 }
3798 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003799 if (curproxy->conf.logformat_string != default_http_log_format &&
3800 curproxy->conf.logformat_string != default_tcp_log_format &&
3801 curproxy->conf.logformat_string != clf_http_log_format)
3802 free(curproxy->conf.logformat_string);
3803 curproxy->conf.logformat_string = logformat;
3804
3805 free(curproxy->conf.lfs_file);
3806 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3807 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003808 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003809 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003811 if (curproxy->conf.logformat_string != default_http_log_format &&
3812 curproxy->conf.logformat_string != default_tcp_log_format &&
3813 curproxy->conf.logformat_string != clf_http_log_format)
3814 free(curproxy->conf.logformat_string);
3815 curproxy->conf.logformat_string = default_tcp_log_format;
3816
3817 free(curproxy->conf.lfs_file);
3818 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3819 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 else if (!strcmp(args[1], "tcpka")) {
3822 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003823 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003824 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003825
3826 if (curproxy->cap & PR_CAP_FE)
3827 curproxy->options |= PR_O_TCP_CLI_KA;
3828 if (curproxy->cap & PR_CAP_BE)
3829 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 }
3831 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003832 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_WARN;
3834
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003836 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003837 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003838 curproxy->options2 &= ~PR_O2_CHK_ANY;
3839 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 if (!*args[2]) { /* no argument */
3841 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3842 curproxy->check_len = strlen(DEF_CHECK_REQ);
3843 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003844 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 curproxy->check_req = (char *)malloc(reqlen);
3846 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003847 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003849 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 if (*args[4])
3851 reqlen += strlen(args[4]);
3852 else
3853 reqlen += strlen("HTTP/1.0");
3854
3855 curproxy->check_req = (char *)malloc(reqlen);
3856 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003857 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003859 }
3860 else if (!strcmp(args[1], "ssl-hello-chk")) {
3861 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003862 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003864
Willy Tarreaua534fea2008-08-03 12:19:50 +02003865 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003866 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003867 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003868 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 }
Willy Tarreau23677902007-05-08 23:50:35 +02003870 else if (!strcmp(args[1], "smtpchk")) {
3871 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003872 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003873 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003874 curproxy->options2 &= ~PR_O2_CHK_ANY;
3875 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003876
3877 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3878 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3879 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3880 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3881 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3882 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3883 curproxy->check_req = (char *)malloc(reqlen);
3884 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3885 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3886 } else {
3887 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3888 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3889 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3890 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3891 }
3892 }
3893 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003894 else if (!strcmp(args[1], "pgsql-check")) {
3895 /* use PostgreSQL request to check servers' health */
3896 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3897 err_code |= ERR_WARN;
3898
3899 free(curproxy->check_req);
3900 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003901 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003902 curproxy->options2 |= PR_O2_PGSQL_CHK;
3903
3904 if (*(args[2])) {
3905 int cur_arg = 2;
3906
3907 while (*(args[cur_arg])) {
3908 if (strcmp(args[cur_arg], "user") == 0) {
3909 char * packet;
3910 uint32_t packet_len;
3911 uint32_t pv;
3912
3913 /* suboption header - needs additional argument for it */
3914 if (*(args[cur_arg+1]) == 0) {
3915 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3916 file, linenum, args[0], args[1], args[cur_arg]);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919 }
3920
3921 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3922 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3923 pv = htonl(0x30000); /* protocol version 3.0 */
3924
3925 packet = (char*) calloc(1, packet_len);
3926
3927 memcpy(packet + 4, &pv, 4);
3928
3929 /* copy "user" */
3930 memcpy(packet + 8, "user", 4);
3931
3932 /* copy username */
3933 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3934
3935 free(curproxy->check_req);
3936 curproxy->check_req = packet;
3937 curproxy->check_len = packet_len;
3938
3939 packet_len = htonl(packet_len);
3940 memcpy(packet, &packet_len, 4);
3941 cur_arg += 2;
3942 } else {
3943 /* unknown suboption - catchall */
3944 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3945 file, linenum, args[0], args[1]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949 } /* end while loop */
3950 }
3951 }
3952
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003953 else if (!strcmp(args[1], "redis-check")) {
3954 /* use REDIS PING request to check servers' health */
3955 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3956 err_code |= ERR_WARN;
3957
3958 free(curproxy->check_req);
3959 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003960 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003961 curproxy->options2 |= PR_O2_REDIS_CHK;
3962
3963 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3964 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3965 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3966 }
3967
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003968 else if (!strcmp(args[1], "mysql-check")) {
3969 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3971 err_code |= ERR_WARN;
3972
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003973 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003974 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003975 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003976 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003977
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003978 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003979 * const char mysql40_client_auth_pkt[] = {
3980 * "\x0e\x00\x00" // packet length
3981 * "\x01" // packet number
3982 * "\x00\x00" // client capabilities
3983 * "\x00\x00\x01" // max packet
3984 * "haproxy\x00" // username (null terminated string)
3985 * "\x00" // filler (always 0x00)
3986 * "\x01\x00\x00" // packet length
3987 * "\x00" // packet number
3988 * "\x01" // COM_QUIT command
3989 * };
3990 */
3991
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003992 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3993 * const char mysql41_client_auth_pkt[] = {
3994 * "\x0e\x00\x00\" // packet length
3995 * "\x01" // packet number
3996 * "\x00\x00\x00\x00" // client capabilities
3997 * "\x00\x00\x00\x01" // max packet
3998 * "\x21" // character set (UTF-8)
3999 * char[23] // All zeroes
4000 * "haproxy\x00" // username (null terminated string)
4001 * "\x00" // filler (always 0x00)
4002 * "\x01\x00\x00" // packet length
4003 * "\x00" // packet number
4004 * "\x01" // COM_QUIT command
4005 * };
4006 */
4007
4008
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004009 if (*(args[2])) {
4010 int cur_arg = 2;
4011
4012 while (*(args[cur_arg])) {
4013 if (strcmp(args[cur_arg], "user") == 0) {
4014 char *mysqluser;
4015 int packetlen, reqlen, userlen;
4016
4017 /* suboption header - needs additional argument for it */
4018 if (*(args[cur_arg+1]) == 0) {
4019 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4020 file, linenum, args[0], args[1], args[cur_arg]);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023 }
4024 mysqluser = args[cur_arg + 1];
4025 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004026
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004027 if (*(args[cur_arg+2])) {
4028 if (!strcmp(args[cur_arg+2], "post-41")) {
4029 packetlen = userlen + 7 + 27;
4030 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004031
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004032 free(curproxy->check_req);
4033 curproxy->check_req = (char *)calloc(1, reqlen);
4034 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004035
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004036 snprintf(curproxy->check_req, 4, "%c%c%c",
4037 ((unsigned char) packetlen & 0xff),
4038 ((unsigned char) (packetlen >> 8) & 0xff),
4039 ((unsigned char) (packetlen >> 16) & 0xff));
4040
4041 curproxy->check_req[3] = 1;
4042 curproxy->check_req[5] = 130;
4043 curproxy->check_req[11] = 1;
4044 curproxy->check_req[12] = 33;
4045 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4046 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4047 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4048 cur_arg += 3;
4049 } else {
4050 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054 } else {
4055 packetlen = userlen + 7;
4056 reqlen = packetlen + 9;
4057
4058 free(curproxy->check_req);
4059 curproxy->check_req = (char *)calloc(1, reqlen);
4060 curproxy->check_len = reqlen;
4061
4062 snprintf(curproxy->check_req, 4, "%c%c%c",
4063 ((unsigned char) packetlen & 0xff),
4064 ((unsigned char) (packetlen >> 8) & 0xff),
4065 ((unsigned char) (packetlen >> 16) & 0xff));
4066
4067 curproxy->check_req[3] = 1;
4068 curproxy->check_req[5] = 128;
4069 curproxy->check_req[8] = 1;
4070 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4071 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4072 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4073 cur_arg += 2;
4074 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004075 } else {
4076 /* unknown suboption - catchall */
4077 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4078 file, linenum, args[0], args[1]);
4079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
4081 }
4082 } /* end while loop */
4083 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004084 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004085 else if (!strcmp(args[1], "ldap-check")) {
4086 /* use LDAP request to check servers' health */
4087 free(curproxy->check_req);
4088 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004089 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004090 curproxy->options2 |= PR_O2_LDAP_CHK;
4091
4092 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4093 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4094 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4095 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004096 else if (!strcmp(args[1], "tcp-check")) {
4097 /* use raw TCPCHK send/expect to check servers' health */
4098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4099 err_code |= ERR_WARN;
4100
4101 free(curproxy->check_req);
4102 curproxy->check_req = NULL;
4103 curproxy->options2 &= ~PR_O2_CHK_ANY;
4104 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4105 }
Simon Horman98637e52014-06-20 12:30:16 +09004106 else if (!strcmp(args[1], "external-check")) {
4107 /* excute an external command to check servers' health */
4108 free(curproxy->check_req);
4109 curproxy->check_req = NULL;
4110 curproxy->options2 &= ~PR_O2_CHK_ANY;
4111 curproxy->options2 |= PR_O2_EXT_CHK;
4112 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004113 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004114 int cur_arg;
4115
4116 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4117 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004118 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004119
Willy Tarreau87cf5142011-08-19 22:57:24 +02004120 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004121
4122 free(curproxy->fwdfor_hdr_name);
4123 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4124 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4125
4126 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4127 cur_arg = 2;
4128 while (*(args[cur_arg])) {
4129 if (!strcmp(args[cur_arg], "except")) {
4130 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004131 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004132 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4133 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004136 }
4137 /* flush useless bits */
4138 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004139 cur_arg += 2;
4140 } else if (!strcmp(args[cur_arg], "header")) {
4141 /* suboption header - needs additional argument for it */
4142 if (*(args[cur_arg+1]) == 0) {
4143 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4144 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004147 }
4148 free(curproxy->fwdfor_hdr_name);
4149 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4150 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4151 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004152 } else if (!strcmp(args[cur_arg], "if-none")) {
4153 curproxy->options &= ~PR_O_FF_ALWAYS;
4154 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004155 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004156 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004157 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004158 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004161 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004162 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004163 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004164 else if (!strcmp(args[1], "originalto")) {
4165 int cur_arg;
4166
4167 /* insert x-original-to field, but not for the IP address listed as an except.
4168 * set default options (ie: bitfield, header name, etc)
4169 */
4170
4171 curproxy->options |= PR_O_ORGTO;
4172
4173 free(curproxy->orgto_hdr_name);
4174 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4175 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4176
Willy Tarreau87cf5142011-08-19 22:57:24 +02004177 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004178 cur_arg = 2;
4179 while (*(args[cur_arg])) {
4180 if (!strcmp(args[cur_arg], "except")) {
4181 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004182 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 +02004183 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4184 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004187 }
4188 /* flush useless bits */
4189 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4190 cur_arg += 2;
4191 } else if (!strcmp(args[cur_arg], "header")) {
4192 /* suboption header - needs additional argument for it */
4193 if (*(args[cur_arg+1]) == 0) {
4194 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4195 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004198 }
4199 free(curproxy->orgto_hdr_name);
4200 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4201 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4202 cur_arg += 2;
4203 } else {
4204 /* unknown suboption - catchall */
4205 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4206 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004209 }
4210 } /* end while loop */
4211 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 else {
4213 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 }
Willy Tarreau93893792009-07-23 13:19:11 +02004217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004219 else if (!strcmp(args[0], "default_backend")) {
4220 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004221 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004222
4223 if (*(args[1]) == 0) {
4224 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004227 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004228 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004229 curproxy->defbe.name = strdup(args[1]);
4230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004232 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004234
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004235 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4236 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 +01004237 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004239 /* enable reconnections to dispatch */
4240 curproxy->options |= PR_O_REDISP;
4241 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004242 else if (!strcmp(args[0], "http-check")) {
4243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004245
4246 if (strcmp(args[1], "disable-on-404") == 0) {
4247 /* enable a graceful server shutdown on an HTTP 404 response */
4248 curproxy->options |= PR_O_DISABLE404;
4249 }
Willy Tarreauef781042010-01-27 11:53:01 +01004250 else if (strcmp(args[1], "send-state") == 0) {
4251 /* enable emission of the apparent state of a server in HTTP checks */
4252 curproxy->options2 |= PR_O2_CHK_SNDST;
4253 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004254 else if (strcmp(args[1], "expect") == 0) {
4255 const char *ptr_arg;
4256 int cur_arg;
4257
4258 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4259 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263
4264 cur_arg = 2;
4265 /* consider exclamation marks, sole or at the beginning of a word */
4266 while (*(ptr_arg = args[cur_arg])) {
4267 while (*ptr_arg == '!') {
4268 curproxy->options2 ^= PR_O2_EXP_INV;
4269 ptr_arg++;
4270 }
4271 if (*ptr_arg)
4272 break;
4273 cur_arg++;
4274 }
4275 /* now ptr_arg points to the beginning of a word past any possible
4276 * exclamation mark, and cur_arg is the argument which holds this word.
4277 */
4278 if (strcmp(ptr_arg, "status") == 0) {
4279 if (!*(args[cur_arg + 1])) {
4280 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4281 file, linenum, args[0], args[1], ptr_arg);
4282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
4285 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004286 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004287 curproxy->expect_str = strdup(args[cur_arg + 1]);
4288 }
4289 else if (strcmp(ptr_arg, "string") == 0) {
4290 if (!*(args[cur_arg + 1])) {
4291 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4292 file, linenum, args[0], args[1], ptr_arg);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004297 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004298 curproxy->expect_str = strdup(args[cur_arg + 1]);
4299 }
4300 else if (strcmp(ptr_arg, "rstatus") == 0) {
4301 if (!*(args[cur_arg + 1])) {
4302 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4303 file, linenum, args[0], args[1], ptr_arg);
4304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004308 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004309 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004310 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004311 free(curproxy->expect_regex);
4312 curproxy->expect_regex = NULL;
4313 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004314 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004315 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4316 error = NULL;
4317 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4318 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4319 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4320 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324 }
4325 else if (strcmp(ptr_arg, "rstring") == 0) {
4326 if (!*(args[cur_arg + 1])) {
4327 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4328 file, linenum, args[0], args[1], ptr_arg);
4329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004333 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004334 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004335 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004336 free(curproxy->expect_regex);
4337 curproxy->expect_regex = NULL;
4338 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004339 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004340 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4341 error = NULL;
4342 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4343 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4344 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4345 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349 }
4350 else {
4351 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4352 file, linenum, args[0], args[1], ptr_arg);
4353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
4355 }
4356 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004357 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004358 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 +02004359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004361 }
4362 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004363 else if (!strcmp(args[0], "tcp-check")) {
4364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4365 err_code |= ERR_WARN;
4366
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004367 if (strcmp(args[1], "connect") == 0) {
4368 const char *ptr_arg;
4369 int cur_arg;
4370 struct tcpcheck_rule *tcpcheck;
4371 struct list *l;
4372
4373 /* check if first rule is also a 'connect' action */
4374 l = (struct list *)&curproxy->tcpcheck_rules;
4375 if (l->p != l->n) {
4376 tcpcheck = (struct tcpcheck_rule *)l->n;
4377 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4378 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4379 file, linenum);
4380 err_code |= ERR_ALERT | ERR_FATAL;
4381 goto out;
4382 }
4383 }
4384
4385 cur_arg = 2;
4386 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4387 tcpcheck->action = TCPCHK_ACT_CONNECT;
4388
4389 /* parsing each parameters to fill up the rule */
4390 while (*(ptr_arg = args[cur_arg])) {
4391 /* tcp port */
4392 if (strcmp(args[cur_arg], "port") == 0) {
4393 if ( (atol(args[cur_arg + 1]) > 65535) ||
4394 (atol(args[cur_arg + 1]) < 1) ){
4395 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4396 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
4400 tcpcheck->port = atol(args[cur_arg + 1]);
4401 cur_arg += 2;
4402 }
4403 /* send proxy protocol */
4404 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4405 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4406 cur_arg++;
4407 }
4408#ifdef USE_OPENSSL
4409 else if (strcmp(args[cur_arg], "ssl") == 0) {
4410 curproxy->options |= PR_O_TCPCHK_SSL;
4411 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4412 cur_arg++;
4413 }
4414#endif /* USE_OPENSSL */
4415 else {
4416#ifdef USE_OPENSSL
4417 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4418#else /* USE_OPENSSL */
4419 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4420#endif /* USE_OPENSSL */
4421 file, linenum, args[0], args[1], args[cur_arg]);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
4425
4426 }
4427
4428 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4429 }
4430 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004431 if (! *(args[2]) ) {
4432 /* SEND string expected */
4433 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4434 file, linenum, args[0], args[1], args[2]);
4435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
4437 } else {
4438 struct tcpcheck_rule *tcpcheck;
4439
4440 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4441
4442 tcpcheck->action = TCPCHK_ACT_SEND;
4443 tcpcheck->string_len = strlen(args[2]);
4444 tcpcheck->string = strdup(args[2]);
4445 tcpcheck->expect_regex = NULL;
4446
4447 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4448 }
4449 }
4450 else if (strcmp(args[1], "send-binary") == 0) {
4451 if (! *(args[2]) ) {
4452 /* SEND binary string expected */
4453 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4454 file, linenum, args[0], args[1], args[2]);
4455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
4457 } else {
4458 struct tcpcheck_rule *tcpcheck;
4459 char *err = NULL;
4460
4461 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4462
4463 tcpcheck->action = TCPCHK_ACT_SEND;
4464 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4465 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4466 file, linenum, args[0], args[1], args[2], err);
4467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
4470 tcpcheck->expect_regex = NULL;
4471
4472 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4473 }
4474 }
4475 else if (strcmp(args[1], "expect") == 0) {
4476 const char *ptr_arg;
4477 int cur_arg;
4478 int inverse = 0;
4479
4480 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4481 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
4484 }
4485
4486 cur_arg = 2;
4487 /* consider exclamation marks, sole or at the beginning of a word */
4488 while (*(ptr_arg = args[cur_arg])) {
4489 while (*ptr_arg == '!') {
4490 inverse = !inverse;
4491 ptr_arg++;
4492 }
4493 if (*ptr_arg)
4494 break;
4495 cur_arg++;
4496 }
4497 /* now ptr_arg points to the beginning of a word past any possible
4498 * exclamation mark, and cur_arg is the argument which holds this word.
4499 */
4500 if (strcmp(ptr_arg, "binary") == 0) {
4501 if (!*(args[cur_arg + 1])) {
4502 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4503 file, linenum, args[0], args[1], ptr_arg);
4504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 }
4507 struct tcpcheck_rule *tcpcheck;
4508 char *err = NULL;
4509
4510 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4511
4512 tcpcheck->action = TCPCHK_ACT_EXPECT;
4513 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4514 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4515 file, linenum, args[0], args[1], args[2], err);
4516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
4518 }
4519 tcpcheck->expect_regex = NULL;
4520 tcpcheck->inverse = inverse;
4521
4522 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4523 }
4524 else if (strcmp(ptr_arg, "string") == 0) {
4525 if (!*(args[cur_arg + 1])) {
4526 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4527 file, linenum, args[0], args[1], ptr_arg);
4528 err_code |= ERR_ALERT | ERR_FATAL;
4529 goto out;
4530 }
4531 struct tcpcheck_rule *tcpcheck;
4532
4533 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4534
4535 tcpcheck->action = TCPCHK_ACT_EXPECT;
4536 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4537 tcpcheck->string = strdup(args[cur_arg + 1]);
4538 tcpcheck->expect_regex = NULL;
4539 tcpcheck->inverse = inverse;
4540
4541 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4542 }
4543 else if (strcmp(ptr_arg, "rstring") == 0) {
4544 if (!*(args[cur_arg + 1])) {
4545 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4546 file, linenum, args[0], args[1], ptr_arg);
4547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
4549 }
4550 struct tcpcheck_rule *tcpcheck;
4551
4552 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4553
4554 tcpcheck->action = TCPCHK_ACT_EXPECT;
4555 tcpcheck->string_len = 0;
4556 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004557 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4558 error = NULL;
4559 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4560 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4561 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4562 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004563 err_code |= ERR_ALERT | ERR_FATAL;
4564 goto out;
4565 }
4566 tcpcheck->inverse = inverse;
4567
4568 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4569 }
4570 else {
4571 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4572 file, linenum, args[0], args[1], ptr_arg);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576 }
4577 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004578 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
4581 }
4582 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004583 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004584 if (curproxy == &defproxy) {
4585 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004588 }
4589
Willy Tarreaub80c2302007-11-30 20:51:32 +01004590 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004591 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004592
4593 if (strcmp(args[1], "fail") == 0) {
4594 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004595 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004596 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4597 file, linenum, args[0], args[1]);
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
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004602 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4603 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4604 file, linenum, args[0], args[1], errmsg);
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 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4609 }
4610 else {
4611 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004614 }
4615 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616#ifdef TPROXY
4617 else if (!strcmp(args[0], "transparent")) {
4618 /* enable transparent proxy connections */
4619 curproxy->options |= PR_O_TRANSP;
4620 }
4621#endif
4622 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004623 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004625
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 if (*(args[1]) == 0) {
4627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 }
4631 curproxy->maxconn = atol(args[1]);
4632 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004633 else if (!strcmp(args[0], "backlog")) { /* backlog */
4634 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004636
4637 if (*(args[1]) == 0) {
4638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004641 }
4642 curproxy->backlog = atol(args[1]);
4643 }
Willy Tarreau86034312006-12-29 00:10:33 +01004644 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004645 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004646 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004647
Willy Tarreau86034312006-12-29 00:10:33 +01004648 if (*(args[1]) == 0) {
4649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004652 }
4653 curproxy->fullconn = atol(args[1]);
4654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4656 if (*(args[1]) == 0) {
4657 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004658 err_code |= ERR_ALERT | ERR_FATAL;
4659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004660 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004661 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4662 if (err) {
4663 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4664 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004665 err_code |= ERR_ALERT | ERR_FATAL;
4666 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004667 }
4668 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
4670 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004671 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004672 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004673 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004674
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 if (curproxy == &defproxy) {
4676 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004680 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004681 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004682
Willy Tarreau902636f2013-03-10 19:44:48 +01004683 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004684 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004685 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004686 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004687 goto out;
4688 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004689
4690 proto = protocol_by_family(sk->ss_family);
4691 if (!proto || !proto->connect) {
4692 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4693 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696 }
4697
4698 if (port1 != port2) {
4699 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4700 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004704
4705 if (!port1) {
4706 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4707 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004711
Willy Tarreaud5191e72010-02-09 20:50:45 +01004712 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004713 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 }
4715 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004717 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004718
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004719 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4720 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004725 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004726 /**
4727 * The syntax for hash-type config element is
4728 * hash-type {map-based|consistent} [[<algo>] avalanche]
4729 *
4730 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4731 */
4732 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004733
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004734 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4735 err_code |= ERR_WARN;
4736
4737 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004738 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4739 }
4740 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004741 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4742 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004743 else if (strcmp(args[1], "avalanche") == 0) {
4744 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]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004747 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004748 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004749 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
4752 }
Bhaskar98634f02013-10-29 23:30:51 -04004753
4754 /* set the hash function to use */
4755 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004756 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004757 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004758
4759 /* if consistent with no argument, then avalanche modifier is also applied */
4760 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4761 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004762 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004763 /* set the hash function */
4764 if (!strcmp(args[2], "sdbm")) {
4765 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4766 }
4767 else if (!strcmp(args[2], "djb2")) {
4768 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004769 } else if (!strcmp(args[2], "wt6")) {
4770 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004771 }
4772 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004773 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 -05004774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 }
4777
4778 /* set the hash modifier */
4779 if (!strcmp(args[3], "avalanche")) {
4780 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4781 }
4782 else if (*args[3]) {
4783 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004787 }
William Lallemanda73203e2012-03-12 12:48:57 +01004788 }
William Lallemanda73203e2012-03-12 12:48:57 +01004789 else if (strcmp(args[0], "unique-id-format") == 0) {
4790 if (!*(args[1])) {
4791 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
William Lallemand3203ff42012-11-11 17:30:56 +01004795 if (*(args[2])) {
4796 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004800 free(curproxy->conf.uniqueid_format_string);
4801 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004802
Willy Tarreau62a61232013-04-12 18:13:46 +02004803 free(curproxy->conf.uif_file);
4804 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4805 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004806 }
William Lallemanda73203e2012-03-12 12:48:57 +01004807
4808 else if (strcmp(args[0], "unique-id-header") == 0) {
4809 if (!*(args[1])) {
4810 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813 }
4814 free(curproxy->header_unique_id);
4815 curproxy->header_unique_id = strdup(args[1]);
4816 }
4817
William Lallemand723b73a2012-02-08 16:37:49 +01004818 else if (strcmp(args[0], "log-format") == 0) {
4819 if (!*(args[1])) {
4820 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823 }
William Lallemand3203ff42012-11-11 17:30:56 +01004824 if (*(args[2])) {
4825 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
4828 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004829
Willy Tarreau62a61232013-04-12 18:13:46 +02004830 if (curproxy->conf.logformat_string != default_http_log_format &&
4831 curproxy->conf.logformat_string != default_tcp_log_format &&
4832 curproxy->conf.logformat_string != clf_http_log_format)
4833 free(curproxy->conf.logformat_string);
4834 curproxy->conf.logformat_string = strdup(args[1]);
4835
4836 free(curproxy->conf.lfs_file);
4837 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4838 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004839
4840 /* get a chance to improve log-format error reporting by
4841 * reporting the correct line-number when possible.
4842 */
4843 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4844 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4845 file, linenum, curproxy->id);
4846 err_code |= ERR_WARN;
4847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 }
William Lallemand723b73a2012-02-08 16:37:49 +01004849
William Lallemand0f99e342011-10-12 17:50:54 +02004850 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4851 /* delete previous herited or defined syslog servers */
4852 struct logsrv *back;
4853
4854 if (*(args[1]) != 0) {
4855 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4856 err_code |= ERR_ALERT | ERR_FATAL;
4857 goto out;
4858 }
4859
William Lallemand723b73a2012-02-08 16:37:49 +01004860 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4861 LIST_DEL(&tmplogsrv->list);
4862 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004863 }
4864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004866 struct logsrv *logsrv;
4867
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004869 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004870 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004871 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004872 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004873 LIST_INIT(&node->list);
4874 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004876 }
4877 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004878 struct sockaddr_storage *sk;
4879 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004880 int arg = 0;
4881 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004882
4883 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884
Willy Tarreau18324f52014-06-27 18:10:07 +02004885 /* just after the address, a length may be specified */
4886 if (strcmp(args[arg+2], "len") == 0) {
4887 len = atoi(args[arg+3]);
4888 if (len < 80 || len > 65535) {
4889 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4890 file, linenum, args[arg+3]);
4891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893 }
4894 logsrv->maxlen = len;
4895
4896 /* skip these two args */
4897 arg += 2;
4898 }
4899 else
4900 logsrv->maxlen = MAX_SYSLOG_LEN;
4901
4902 if (logsrv->maxlen > global.max_syslog_len) {
4903 global.max_syslog_len = logsrv->maxlen;
4904 logline = realloc(logline, global.max_syslog_len + 1);
4905 }
4906
4907 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004908 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004909 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
4912
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914
William Lallemand0f99e342011-10-12 17:50:54 +02004915 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004916 if (*(args[arg+3])) {
4917 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004918 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004919 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
4922
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
4924 }
4925
William Lallemand0f99e342011-10-12 17:50:54 +02004926 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02004927 if (*(args[arg+4])) {
4928 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004929 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004930 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
4933
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004934 }
4935 }
4936
Willy Tarreau902636f2013-03-10 19:44:48 +01004937 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004938 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004939 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004940 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004941 goto out;
4942 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004943
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004944 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004945
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004946 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004947 if (port1 != port2) {
4948 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4949 file, linenum, args[0], args[1]);
4950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
4953
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004954 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004955 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
William Lallemand0f99e342011-10-12 17:50:54 +02004957
4958 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960 else {
4961 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4962 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966 }
4967 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004968 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004969 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004970 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004971 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004972
Willy Tarreau977b8e42006-12-29 14:19:17 +01004973 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004974 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004975
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004977 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4978 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004982
4983 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004984 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4985 free(curproxy->conn_src.iface_name);
4986 curproxy->conn_src.iface_name = NULL;
4987 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004988
Willy Tarreau902636f2013-03-10 19:44:48 +01004989 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004990 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004991 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004992 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004993 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004994 goto out;
4995 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004996
4997 proto = protocol_by_family(sk->ss_family);
4998 if (!proto || !proto->connect) {
4999 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005000 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005004
5005 if (port1 != port2) {
5006 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5007 file, linenum, args[0], args[1]);
5008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010 }
5011
Willy Tarreauef9a3602012-12-08 22:29:20 +01005012 curproxy->conn_src.source_addr = *sk;
5013 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005014
5015 cur_arg = 2;
5016 while (*(args[cur_arg])) {
5017 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005018#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5019#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005020 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005021 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\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#endif
5027 if (!*args[cur_arg + 1]) {
5028 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5029 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005032 }
5033
5034 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005035 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5036 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005037 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005038 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5039 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005040 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5041 char *name, *end;
5042
5043 name = args[cur_arg+1] + 7;
5044 while (isspace(*name))
5045 name++;
5046
5047 end = name;
5048 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5049 end++;
5050
Willy Tarreauef9a3602012-12-08 22:29:20 +01005051 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5052 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5053 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5054 curproxy->conn_src.bind_hdr_len = end - name;
5055 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5056 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5057 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005058
5059 /* now look for an occurrence number */
5060 while (isspace(*end))
5061 end++;
5062 if (*end == ',') {
5063 end++;
5064 name = end;
5065 if (*end == '-')
5066 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005067 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005068 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005069 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005070 }
5071
Willy Tarreauef9a3602012-12-08 22:29:20 +01005072 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005073 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5074 " occurrences values smaller than %d.\n",
5075 file, linenum, MAX_HDR_HISTORY);
5076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
5078 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005079 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005080 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005081
Willy Tarreau902636f2013-03-10 19:44:48 +01005082 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005083 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005084 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005085 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005086 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005087 goto out;
5088 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005089
5090 proto = protocol_by_family(sk->ss_family);
5091 if (!proto || !proto->connect) {
5092 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5093 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
5096 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005097
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005098 if (port1 != port2) {
5099 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5100 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
5103 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005104 curproxy->conn_src.tproxy_addr = *sk;
5105 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005106 }
5107 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005108#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005109 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005110#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005111#else /* no TPROXY support */
5112 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005113 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005116#endif
5117 cur_arg += 2;
5118 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005119 }
5120
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005121 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5122#ifdef SO_BINDTODEVICE
5123 if (!*args[cur_arg + 1]) {
5124 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5125 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005128 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005129 free(curproxy->conn_src.iface_name);
5130 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5131 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005132 global.last_checks |= LSTCHK_NETADM;
5133#else
5134 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5135 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005138#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005139 cur_arg += 2;
5140 continue;
5141 }
5142 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005143 file, linenum, args[0], "interface", "usesrc");
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 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005148 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5149 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5150 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5157 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005158 err_code |= ERR_ALERT | ERR_FATAL;
5159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161
5162 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005163 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005164 args[0], args[1], args[2], (const char **)args+3);
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], "reqdel")) { /* delete request header from a 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_REMOVE, 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], "reqdeny")) { /* deny a request if a header matches this regex */
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_DENY, 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], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 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 }
5189 else if (!strcmp(args[0], "reqallow")) { /* allow 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_ALLOW, 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 Tarreaubaaee002006-06-26 02:48:02 +02005195 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005196 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005199 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005201 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005202 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005203 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005205 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005206 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005208 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005209
5210 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5211 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 +01005212 }
5213 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005215 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005216 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005218 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005219
5220 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5221 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 +01005222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5226 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005230
5231 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005232 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005233 args[0], args[1], args[2], (const char **)args+3);
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], "reqidel")) { /* delete request header from a 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_REMOVE, 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], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
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_DENY, 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], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, 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 }
5258 else if (!strcmp(args[0], "reqiallow")) { /* allow 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_ALLOW, 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 Tarreaubaaee002006-06-26 02:48:02 +02005264 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005265 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005267 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005268 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005270 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005273 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005274
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 if (curproxy == &defproxy) {
5276 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005280 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005281 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 if (*(args[1]) == 0) {
5284 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005288
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005289 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005290 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5291 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5292 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005296 err_code |= warnif_cond_conflicts(cond,
5297 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5298 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005299 }
5300 else if (*args[2]) {
5301 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5302 file, linenum, args[0], args[2]);
5303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
5305 }
5306
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005307 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005308 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005309 wl->s = strdup(args[1]);
5310 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005311 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5316 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005320
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_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005323 args[0], args[1], args[2], (const char **)args+3);
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], "rspdel")) { /* delete 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_REMOVE, 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], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005336 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005337 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005338 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 }
5341 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
5348
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_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005351 args[0], args[1], args[2], (const char **)args+3);
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], "rspidel")) { /* delete 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_REMOVE, 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], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005364 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005365 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005366 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
5369 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005370 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005371
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 if (curproxy == &defproxy) {
5373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005377 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005378 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 if (*(args[1]) == 0) {
5381 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005384 }
5385
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005386 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005387 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5388 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5389 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005393 err_code |= warnif_cond_conflicts(cond,
5394 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5395 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005396 }
5397 else if (*args[2]) {
5398 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5399 file, linenum, args[0], args[2]);
5400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
5402 }
5403
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005404 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005405 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005406 wl->s = strdup(args[1]);
5407 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408 }
5409 else if (!strcmp(args[0], "errorloc") ||
5410 !strcmp(args[0], "errorloc302") ||
5411 !strcmp(args[0], "errorloc303")) { /* error location */
5412 int errnum, errlen;
5413 char *err;
5414
Willy Tarreau977b8e42006-12-29 14:19:17 +01005415 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005416 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005417
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005419 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 }
5423
5424 errnum = atol(args[1]);
5425 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005426 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5427 err = malloc(errlen);
5428 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005429 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005430 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5431 err = malloc(errlen);
5432 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
5434
Willy Tarreau0f772532006-12-23 20:51:41 +01005435 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5436 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005437 chunk_destroy(&curproxy->errmsg[rc]);
5438 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005439 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005442
5443 if (rc >= HTTP_ERR_SIZE) {
5444 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5445 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 free(err);
5447 }
5448 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005449 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5450 int errnum, errlen, fd;
5451 char *err;
5452 struct stat stat;
5453
5454 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005455 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005456
5457 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005458 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005461 }
5462
5463 fd = open(args[2], O_RDONLY);
5464 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5465 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5466 file, linenum, args[2], args[1]);
5467 if (fd >= 0)
5468 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005471 }
5472
Willy Tarreau27a674e2009-08-17 07:23:33 +02005473 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005474 errlen = stat.st_size;
5475 } else {
5476 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005477 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005479 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005480 }
5481
5482 err = malloc(errlen); /* malloc() must succeed during parsing */
5483 errnum = read(fd, err, errlen);
5484 if (errnum != errlen) {
5485 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5486 file, linenum, args[2], args[1]);
5487 close(fd);
5488 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005491 }
5492 close(fd);
5493
5494 errnum = atol(args[1]);
5495 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5496 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005497 chunk_destroy(&curproxy->errmsg[rc]);
5498 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005499 break;
5500 }
5501 }
5502
5503 if (rc >= HTTP_ERR_SIZE) {
5504 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5505 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005506 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005507 free(err);
5508 }
5509 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005510 else if (!strcmp(args[0], "compression")) {
5511 struct comp *comp;
5512 if (curproxy->comp == NULL) {
5513 comp = calloc(1, sizeof(struct comp));
5514 curproxy->comp = comp;
5515 } else {
5516 comp = curproxy->comp;
5517 }
5518
5519 if (!strcmp(args[1], "algo")) {
5520 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005521 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005522
William Lallemand82fe75c2012-10-23 10:25:10 +02005523 cur_arg = 2;
5524 if (!*args[cur_arg]) {
5525 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5526 file, linenum, args[0]);
5527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
5530 while (*(args[cur_arg])) {
5531 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5532 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5533 file, linenum, args[0], args[cur_arg]);
5534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536 }
William Lallemand552df672012-11-07 13:21:47 +01005537 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5538 curproxy->comp->algos->end(&ctx);
5539 } else {
5540 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5541 file, linenum, args[0], args[cur_arg]);
5542 err_code |= ERR_ALERT | ERR_FATAL;
5543 goto out;
5544 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005545 cur_arg ++;
5546 continue;
5547 }
5548 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005549 else if (!strcmp(args[1], "offload")) {
5550 comp->offload = 1;
5551 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005552 else if (!strcmp(args[1], "type")) {
5553 int cur_arg;
5554 cur_arg = 2;
5555 if (!*args[cur_arg]) {
5556 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5557 file, linenum, args[0]);
5558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
5560 }
5561 while (*(args[cur_arg])) {
5562 comp_append_type(comp, args[cur_arg]);
5563 cur_arg ++;
5564 continue;
5565 }
5566 }
5567 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005568 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005569 file, linenum, args[0]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005575 struct cfg_kw_list *kwl;
5576 int index;
5577
5578 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5579 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5580 if (kwl->kw[index].section != CFG_LISTEN)
5581 continue;
5582 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5583 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005584 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005585 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005586 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005589 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005590 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005591 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_WARN;
5593 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005594 }
Willy Tarreau93893792009-07-23 13:19:11 +02005595 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005596 }
5597 }
5598 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005599
Willy Tarreau6daf3432008-01-22 16:44:08 +01005600 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 }
Willy Tarreau93893792009-07-23 13:19:11 +02005604 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005605 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005606 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607}
5608
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005609int
5610cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5611{
5612
5613 int err_code = 0;
5614 const char *err;
5615
5616 if (!strcmp(args[0], "userlist")) { /* new userlist */
5617 struct userlist *newul;
5618
5619 if (!*args[1]) {
5620 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5621 file, linenum, args[0]);
5622 err_code |= ERR_ALERT | ERR_FATAL;
5623 goto out;
5624 }
5625
5626 err = invalid_char(args[1]);
5627 if (err) {
5628 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5629 file, linenum, *err, args[0], args[1]);
5630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
5632 }
5633
5634 for (newul = userlist; newul; newul = newul->next)
5635 if (!strcmp(newul->name, args[1])) {
5636 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5637 file, linenum, args[1]);
5638 err_code |= ERR_WARN;
5639 goto out;
5640 }
5641
5642 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5643 if (!newul) {
5644 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5645 err_code |= ERR_ALERT | ERR_ABORT;
5646 goto out;
5647 }
5648
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005649 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005650 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005651 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5652 err_code |= ERR_ALERT | ERR_ABORT;
5653 goto out;
5654 }
5655
5656 newul->next = userlist;
5657 userlist = newul;
5658
5659 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005660 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005661 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005662 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005663
5664 if (!*args[1]) {
5665 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5666 file, linenum, args[0]);
5667 err_code |= ERR_ALERT | ERR_FATAL;
5668 goto out;
5669 }
5670
5671 err = invalid_char(args[1]);
5672 if (err) {
5673 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5674 file, linenum, *err, args[0], args[1]);
5675 err_code |= ERR_ALERT | ERR_FATAL;
5676 goto out;
5677 }
5678
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005679 for (ag = userlist->groups; ag; ag = ag->next)
5680 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005681 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5682 file, linenum, args[1], userlist->name);
5683 err_code |= ERR_ALERT;
5684 goto out;
5685 }
5686
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005687 ag = calloc(1, sizeof(*ag));
5688 if (!ag) {
5689 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5690 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005691 goto out;
5692 }
5693
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005694 ag->name = strdup(args[1]);
5695 if (!ag) {
5696 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5697 err_code |= ERR_ALERT | ERR_ABORT;
5698 goto out;
5699 }
5700
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005701 cur_arg = 2;
5702
5703 while (*args[cur_arg]) {
5704 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005705 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005706 cur_arg += 2;
5707 continue;
5708 } else {
5709 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5710 file, linenum, args[0]);
5711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
5713 }
5714 }
5715
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005716 ag->next = userlist->groups;
5717 userlist->groups = ag;
5718
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005719 } else if (!strcmp(args[0], "user")) { /* new user */
5720 struct auth_users *newuser;
5721 int cur_arg;
5722
5723 if (!*args[1]) {
5724 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5725 file, linenum, args[0]);
5726 err_code |= ERR_ALERT | ERR_FATAL;
5727 goto out;
5728 }
5729
5730 for (newuser = userlist->users; newuser; newuser = newuser->next)
5731 if (!strcmp(newuser->user, args[1])) {
5732 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5733 file, linenum, args[1], userlist->name);
5734 err_code |= ERR_ALERT;
5735 goto out;
5736 }
5737
5738 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5739 if (!newuser) {
5740 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5741 err_code |= ERR_ALERT | ERR_ABORT;
5742 goto out;
5743 }
5744
5745 newuser->user = strdup(args[1]);
5746
5747 newuser->next = userlist->users;
5748 userlist->users = newuser;
5749
5750 cur_arg = 2;
5751
5752 while (*args[cur_arg]) {
5753 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02005754#ifdef CONFIG_HAP_CRYPT
5755 if (!crypt("", args[cur_arg + 1])) {
5756 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5757 file, linenum, newuser->user);
5758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
5760 }
5761#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005762 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5763 file, linenum);
5764 err_code |= ERR_ALERT;
5765#endif
5766 newuser->pass = strdup(args[cur_arg + 1]);
5767 cur_arg += 2;
5768 continue;
5769 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5770 newuser->pass = strdup(args[cur_arg + 1]);
5771 newuser->flags |= AU_O_INSECURE;
5772 cur_arg += 2;
5773 continue;
5774 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005775 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005776 cur_arg += 2;
5777 continue;
5778 } else {
5779 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5780 file, linenum, args[0]);
5781 err_code |= ERR_ALERT | ERR_FATAL;
5782 goto out;
5783 }
5784 }
5785 } else {
5786 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5787 err_code |= ERR_ALERT | ERR_FATAL;
5788 }
5789
5790out:
5791 return err_code;
5792}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793
5794/*
5795 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005796 * Returns the error code, 0 if OK, or any combination of :
5797 * - ERR_ABORT: must abort ASAP
5798 * - ERR_FATAL: we can continue parsing but not start the service
5799 * - ERR_WARN: a warning has been emitted
5800 * - ERR_ALERT: an alert has been emitted
5801 * Only the two first ones can stop processing, the two others are just
5802 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005804int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005806 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 FILE *f;
5808 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005809 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005810 struct cfg_section *cs = NULL;
5811 struct cfg_section *ics;
5812
5813 /* Register internal sections */
5814 if (!cfg_register_section("listen", cfg_parse_listen) ||
5815 !cfg_register_section("frontend", cfg_parse_listen) ||
5816 !cfg_register_section("backend", cfg_parse_listen) ||
5817 !cfg_register_section("ruleset", cfg_parse_listen) ||
5818 !cfg_register_section("defaults", cfg_parse_listen) ||
5819 !cfg_register_section("global", cfg_parse_global) ||
5820 !cfg_register_section("userlist", cfg_parse_users) ||
5821 !cfg_register_section("peers", cfg_parse_peers))
5822 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824 if ((f=fopen(file,"r")) == NULL)
5825 return -1;
5826
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005827 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005828 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005829 char *end;
5830 char *args[MAX_LINE_ARGS + 1];
5831 char *line = thisline;
5832
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 linenum++;
5834
5835 end = line + strlen(line);
5836
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005837 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5838 /* Check if we reached the limit and the last char is not \n.
5839 * Watch out for the last line without the terminating '\n'!
5840 */
5841 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005842 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005843 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005844 }
5845
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005847 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 line++;
5849
5850 arg = 0;
5851 args[arg] = line;
5852
5853 while (*line && arg < MAX_LINE_ARGS) {
5854 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5855 * C equivalent value. Other combinations left unchanged (eg: \1).
5856 */
5857 if (*line == '\\') {
5858 int skip = 0;
5859 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5860 *line = line[1];
5861 skip = 1;
5862 }
5863 else if (line[1] == 'r') {
5864 *line = '\r';
5865 skip = 1;
5866 }
5867 else if (line[1] == 'n') {
5868 *line = '\n';
5869 skip = 1;
5870 }
5871 else if (line[1] == 't') {
5872 *line = '\t';
5873 skip = 1;
5874 }
5875 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005876 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 unsigned char hex1, hex2;
5878 hex1 = toupper(line[2]) - '0';
5879 hex2 = toupper(line[3]) - '0';
5880 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5881 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5882 *line = (hex1<<4) + hex2;
5883 skip = 3;
5884 }
5885 else {
5886 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005887 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 }
5889 }
5890 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005891 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 end -= skip;
5893 }
5894 line++;
5895 }
5896 else if (*line == '#' || *line == '\n' || *line == '\r') {
5897 /* end of string, end of loop */
5898 *line = 0;
5899 break;
5900 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005901 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005903 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005904 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 line++;
5906 args[++arg] = line;
5907 }
5908 else {
5909 line++;
5910 }
5911 }
5912
5913 /* empty line */
5914 if (!**args)
5915 continue;
5916
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005917 if (*line) {
5918 /* we had to stop due to too many args.
5919 * Let's terminate the string, print the offending part then cut the
5920 * last arg.
5921 */
5922 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5923 line++;
5924 *line = '\0';
5925
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005926 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005927 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005928 err_code |= ERR_ALERT | ERR_FATAL;
5929 args[arg] = line;
5930 }
5931
Willy Tarreau540abe42007-05-02 20:50:16 +02005932 /* zero out remaining args and ensure that at least one entry
5933 * is zeroed out.
5934 */
5935 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 args[arg] = line;
5937 }
5938
Willy Tarreau3842f002009-06-14 11:39:52 +02005939 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005940 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005941 char *tmp;
5942
Willy Tarreau3842f002009-06-14 11:39:52 +02005943 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005944 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005945 for (arg=0; *args[arg+1]; arg++)
5946 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005947 *tmp = '\0'; // fix the next arg to \0
5948 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005949 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005950 else if (!strcmp(args[0], "default")) {
5951 kwm = KWM_DEF;
5952 for (arg=0; *args[arg+1]; arg++)
5953 args[arg] = args[arg+1]; // shift args after inversion
5954 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005955
William Lallemand0f99e342011-10-12 17:50:54 +02005956 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5957 strcmp(args[0], "log") != 0) {
5958 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005959 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005960 }
5961
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005962 /* detect section start */
5963 list_for_each_entry(ics, &sections, list) {
5964 if (strcmp(args[0], ics->section_name) == 0) {
5965 cursection = ics->section_name;
5966 cs = ics;
5967 break;
5968 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005969 }
5970
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005972 if (cs)
5973 err_code |= cs->section_parser(file, linenum, args, kwm);
5974 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005975 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005976 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005978
5979 if (err_code & ERR_ABORT)
5980 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005982 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005984 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005985}
5986
Willy Tarreaubb925012009-07-23 13:36:36 +02005987/*
5988 * Returns the error code, 0 if OK, or any combination of :
5989 * - ERR_ABORT: must abort ASAP
5990 * - ERR_FATAL: we can continue parsing but not start the service
5991 * - ERR_WARN: a warning has been emitted
5992 * - ERR_ALERT: an alert has been emitted
5993 * Only the two first ones can stop processing, the two others are just
5994 * indicators.
5995 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005996int check_config_validity()
5997{
5998 int cfgerr = 0;
5999 struct proxy *curproxy = NULL;
6000 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006001 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006002 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006003 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006004
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006005 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006006 /*
6007 * Now, check for the integrity of all that we have collected.
6008 */
6009
6010 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006011 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012
Willy Tarreau193b8c62012-11-22 00:17:38 +01006013 if (!global.tune.max_http_hdr)
6014 global.tune.max_http_hdr = MAX_HTTP_HDR;
6015
6016 if (!global.tune.cookie_len)
6017 global.tune.cookie_len = CAPTURE_LEN;
6018
6019 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6020
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006021 /* Post initialisation of the users and groups lists. */
6022 err_code = userlist_postinit();
6023 if (err_code != ERR_NONE)
6024 goto out;
6025
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006026 /* first, we will invert the proxy list order */
6027 curproxy = NULL;
6028 while (proxy) {
6029 struct proxy *next;
6030
6031 next = proxy->next;
6032 proxy->next = curproxy;
6033 curproxy = proxy;
6034 if (!next)
6035 break;
6036 proxy = next;
6037 }
6038
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006040 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006041 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006042 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006043 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006044 struct http_req_rule *hrqrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006045 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006046 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006047 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006048
Willy Tarreau050536d2012-10-04 08:47:34 +02006049 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006050 /* proxy ID not set, use automatic numbering with first
6051 * spare entry starting with next_pxid.
6052 */
6053 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6054 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6055 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006056 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006057 next_pxid++;
6058
Willy Tarreau55ea7572007-06-17 19:56:27 +02006059
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006061 /* ensure we don't keep listeners uselessly bound */
6062 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063 curproxy = curproxy->next;
6064 continue;
6065 }
6066
Willy Tarreau102df612014-05-07 23:56:38 +02006067 /* Check multi-process mode compatibility for the current proxy */
6068
6069 if (curproxy->bind_proc) {
6070 /* an explicit bind-process was specified, let's check how many
6071 * processes remain.
6072 */
6073 nbproc = popcount(curproxy->bind_proc);
6074
6075 curproxy->bind_proc &= nbits(global.nbproc);
6076 if (!curproxy->bind_proc && nbproc == 1) {
6077 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);
6078 curproxy->bind_proc = 1;
6079 }
6080 else if (!curproxy->bind_proc && nbproc > 1) {
6081 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);
6082 curproxy->bind_proc = 0;
6083 }
6084 }
6085
Willy Tarreau3d209582014-05-09 17:06:11 +02006086 /* check and reduce the bind-proc of each listener */
6087 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6088 unsigned long mask;
6089
6090 if (!bind_conf->bind_proc)
6091 continue;
6092
6093 mask = nbits(global.nbproc);
6094 if (curproxy->bind_proc)
6095 mask &= curproxy->bind_proc;
6096 /* mask cannot be null here thanks to the previous checks */
6097
6098 nbproc = popcount(bind_conf->bind_proc);
6099 bind_conf->bind_proc &= mask;
6100
6101 if (!bind_conf->bind_proc && nbproc == 1) {
6102 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",
6103 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6104 bind_conf->bind_proc = mask & ~(mask - 1);
6105 }
6106 else if (!bind_conf->bind_proc && nbproc > 1) {
6107 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",
6108 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6109 bind_conf->bind_proc = 0;
6110 }
6111 }
6112
Willy Tarreau102df612014-05-07 23:56:38 +02006113 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
6114 * We now check how many processes the proxy will effectively run on.
6115 */
6116
6117 nbproc = global.nbproc;
6118 if (curproxy->bind_proc)
6119 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
6120
6121 if (global.nbproc > 1 && curproxy->table.peers.name) {
6122 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6123 curproxy->id);
6124 cfgerr++;
6125 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006126
Willy Tarreauff01a212009-03-15 13:46:16 +01006127 switch (curproxy->mode) {
6128 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006129 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006130 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006131 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6132 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006133 cfgerr++;
6134 }
6135
6136 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006137 Warning("config : servers will be ignored for %s '%s'.\n",
6138 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006139 break;
6140
6141 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006142 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006143 break;
6144
6145 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006146 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006147 break;
6148 }
6149
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006150 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006151 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006152 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006153 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6154 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006155 cfgerr++;
6156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006158 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006159 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6160 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006161 cfgerr++;
6162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006163#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006164 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006165 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6166 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006167 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006168 }
6169 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006170 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006171 /* If no LB algo is set in a backend, and we're not in
6172 * transparent mode, dispatch mode nor proxy mode, we
6173 * want to use balance roundrobin by default.
6174 */
6175 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6176 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 }
6178 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006179
Willy Tarreau1620ec32011-08-06 17:05:02 +02006180 if (curproxy->options & PR_O_DISPATCH)
6181 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6182 else if (curproxy->options & PR_O_HTTP_PROXY)
6183 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6184 else if (curproxy->options & PR_O_TRANSP)
6185 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006186
Willy Tarreau1620ec32011-08-06 17:05:02 +02006187 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6188 if (curproxy->options & PR_O_DISABLE404) {
6189 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6190 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6191 err_code |= ERR_WARN;
6192 curproxy->options &= ~PR_O_DISABLE404;
6193 }
6194 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6195 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6196 "send-state", proxy_type_str(curproxy), curproxy->id);
6197 err_code |= ERR_WARN;
6198 curproxy->options &= ~PR_O2_CHK_SNDST;
6199 }
Willy Tarreauef781042010-01-27 11:53:01 +01006200 }
6201
Simon Horman98637e52014-06-20 12:30:16 +09006202 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6203 if (!global.external_check) {
6204 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6205 curproxy->id, "option external-check");
6206 cfgerr++;
6207 }
6208 if (!curproxy->check_command) {
6209 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6210 curproxy->id, "option external-check");
6211 cfgerr++;
6212 }
6213 }
6214
6215 if (curproxy->check_command) {
6216 int clear = 0;
6217 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6218 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6219 "external-check command", proxy_type_str(curproxy), curproxy->id);
6220 err_code |= ERR_WARN;
6221 clear = 1;
6222 }
6223 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6224 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6225 curproxy->id, "external-check command");
6226 cfgerr++;
6227 }
6228 if (clear) {
6229 free(curproxy->check_command);
6230 curproxy->check_command = NULL;
6231 }
6232 }
6233
6234 if (curproxy->check_path) {
6235 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6236 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6237 "external-check path", proxy_type_str(curproxy), curproxy->id);
6238 err_code |= ERR_WARN;
6239 free(curproxy->check_path);
6240 curproxy->check_path = NULL;
6241 }
6242 }
6243
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006244 /* if a default backend was specified, let's find it */
6245 if (curproxy->defbe.name) {
6246 struct proxy *target;
6247
Alex Williams96532db2009-11-01 21:27:13 -05006248 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006249 if (!target) {
6250 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6251 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006252 cfgerr++;
6253 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006254 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6255 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006256 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006257 } else {
6258 free(curproxy->defbe.name);
6259 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006260 /* we force the backend to be present on at least all of
6261 * the frontend's processes.
6262 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006263 if (target->bind_proc)
6264 target->bind_proc = curproxy->bind_proc ?
6265 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006266
6267 /* Emit a warning if this proxy also has some servers */
6268 if (curproxy->srv) {
6269 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6270 curproxy->id);
6271 err_code |= ERR_WARN;
6272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 }
6274 }
6275
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006276 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006277 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6278 /* map jump target for ACT_SETBE in req_rep chain */
6279 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006280 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006281 struct proxy *target;
6282
Willy Tarreaua496b602006-12-17 23:15:24 +01006283 if (exp->action != ACT_SETBE)
6284 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006285
Alex Williams96532db2009-11-01 21:27:13 -05006286 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006287 if (!target) {
6288 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6289 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006290 cfgerr++;
6291 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006292 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6293 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006294 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006295 } else {
6296 free((void *)exp->replace);
6297 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006298 /* we force the backend to be present on at least all of
6299 * the frontend's processes.
6300 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006301 if (target->bind_proc)
6302 target->bind_proc = curproxy->bind_proc ?
6303 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006304 }
6305 }
6306 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006307
6308 /* find the target proxy for 'use_backend' rules */
6309 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006310 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006311 struct logformat_node *node;
6312 char *pxname;
6313
6314 /* Try to parse the string as a log format expression. If the result
6315 * of the parsing is only one entry containing a simple string, then
6316 * it's a standard string corresponding to a static rule, thus the
6317 * parsing is cancelled and be.name is restored to be resolved.
6318 */
6319 pxname = rule->be.name;
6320 LIST_INIT(&rule->be.expr);
6321 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6322 curproxy->conf.args.file, curproxy->conf.args.line);
6323 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6324
6325 if (!LIST_ISEMPTY(&rule->be.expr)) {
6326 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6327 rule->dynamic = 1;
6328 free(pxname);
6329 continue;
6330 }
6331 /* simple string: free the expression and fall back to static rule */
6332 free(node->arg);
6333 free(node);
6334 }
6335
6336 rule->dynamic = 0;
6337 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006338
Alex Williams96532db2009-11-01 21:27:13 -05006339 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006340
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006341 if (!target) {
6342 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6343 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006344 cfgerr++;
6345 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006346 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6347 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006348 cfgerr++;
6349 } else {
6350 free((void *)rule->be.name);
6351 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006352 /* we force the backend to be present on at least all of
6353 * the frontend's processes.
6354 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006355 if (target->bind_proc)
6356 target->bind_proc = curproxy->bind_proc ?
6357 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006358 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006359 }
6360
6361 /* find the target proxy for 'use_backend' rules */
6362 list_for_each_entry(srule, &curproxy->server_rules, list) {
6363 struct server *target = findserver(curproxy, srule->srv.name);
6364
6365 if (!target) {
6366 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6367 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6368 cfgerr++;
6369 continue;
6370 }
6371 free((void *)srule->srv.name);
6372 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006373 }
6374
Emeric Brunb982a3d2010-01-04 15:45:53 +01006375 /* find the target table for 'stick' rules */
6376 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6377 struct proxy *target;
6378
Emeric Brun1d33b292010-01-04 15:47:17 +01006379 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6380 if (mrule->flags & STK_IS_STORE)
6381 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6382
Emeric Brunb982a3d2010-01-04 15:45:53 +01006383 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006384 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006385 else
6386 target = curproxy;
6387
6388 if (!target) {
6389 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6390 curproxy->id, mrule->table.name);
6391 cfgerr++;
6392 }
6393 else if (target->table.size == 0) {
6394 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6395 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6396 cfgerr++;
6397 }
Willy Tarreau12785782012-04-27 21:37:17 +02006398 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6399 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006400 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6401 cfgerr++;
6402 }
6403 else {
6404 free((void *)mrule->table.name);
6405 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006406 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006407 }
6408 }
6409
6410 /* find the target table for 'store response' rules */
6411 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6412 struct proxy *target;
6413
Emeric Brun1d33b292010-01-04 15:47:17 +01006414 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6415
Emeric Brunb982a3d2010-01-04 15:45:53 +01006416 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006417 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006418 else
6419 target = curproxy;
6420
6421 if (!target) {
6422 Alert("Proxy '%s': unable to find store table '%s'.\n",
6423 curproxy->id, mrule->table.name);
6424 cfgerr++;
6425 }
6426 else if (target->table.size == 0) {
6427 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6428 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6429 cfgerr++;
6430 }
Willy Tarreau12785782012-04-27 21:37:17 +02006431 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6432 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006433 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6434 cfgerr++;
6435 }
6436 else {
6437 free((void *)mrule->table.name);
6438 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006439 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006440 }
6441 }
6442
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006443 /* find the target table for 'tcp-request' layer 4 rules */
6444 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6445 struct proxy *target;
6446
Willy Tarreaub4c84932013-07-23 19:15:30 +02006447 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006448 continue;
6449
6450 if (trule->act_prm.trk_ctr.table.n)
6451 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6452 else
6453 target = curproxy;
6454
6455 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006456 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6457 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006458 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006459 cfgerr++;
6460 }
6461 else if (target->table.size == 0) {
6462 Alert("Proxy '%s': table '%s' used but not configured.\n",
6463 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6464 cfgerr++;
6465 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006466 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6467 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6468 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 +01006469 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006470 cfgerr++;
6471 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006472 else {
6473 free(trule->act_prm.trk_ctr.table.n);
6474 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006475 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006476 * to pass a list of counters to track and allocate them right here using
6477 * stktable_alloc_data_type().
6478 */
6479 }
6480 }
6481
Willy Tarreaud1f96522010-08-03 19:34:32 +02006482 /* find the target table for 'tcp-request' layer 6 rules */
6483 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6484 struct proxy *target;
6485
Willy Tarreaub4c84932013-07-23 19:15:30 +02006486 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006487 continue;
6488
6489 if (trule->act_prm.trk_ctr.table.n)
6490 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6491 else
6492 target = curproxy;
6493
6494 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006495 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6496 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006497 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006498 cfgerr++;
6499 }
6500 else if (target->table.size == 0) {
6501 Alert("Proxy '%s': table '%s' used but not configured.\n",
6502 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6503 cfgerr++;
6504 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006505 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6506 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6507 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 +01006508 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006509 cfgerr++;
6510 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006511 else {
6512 free(trule->act_prm.trk_ctr.table.n);
6513 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006514 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006515 * to pass a list of counters to track and allocate them right here using
6516 * stktable_alloc_data_type().
6517 */
6518 }
6519 }
6520
Willy Tarreau09448f72014-06-25 18:12:15 +02006521 /* find the target table for 'http-request' layer 7 rules */
6522 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6523 struct proxy *target;
6524
6525 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6526 continue;
6527
6528 if (hrqrule->act_prm.trk_ctr.table.n)
6529 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6530 else
6531 target = curproxy;
6532
6533 if (!target) {
6534 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6535 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6536 http_req_trk_idx(hrqrule->action));
6537 cfgerr++;
6538 }
6539 else if (target->table.size == 0) {
6540 Alert("Proxy '%s': table '%s' used but not configured.\n",
6541 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6542 cfgerr++;
6543 }
6544 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6545 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6546 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6547 http_req_trk_idx(hrqrule->action));
6548 cfgerr++;
6549 }
6550 else {
6551 free(hrqrule->act_prm.trk_ctr.table.n);
6552 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6553 /* Note: if we decide to enhance the track-sc syntax, we may be able
6554 * to pass a list of counters to track and allocate them right here using
6555 * stktable_alloc_data_type().
6556 */
6557 }
6558 }
6559
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006560 /* move any "block" rules at the beginning of the http-request rules */
6561 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6562 /* insert block_rules into http_req_rules at the beginning */
6563 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6564 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6565 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6566 curproxy->http_req_rules.n = curproxy->block_rules.n;
6567 LIST_INIT(&curproxy->block_rules);
6568 }
6569
Emeric Brun32da3c42010-09-23 18:39:19 +02006570 if (curproxy->table.peers.name) {
6571 struct peers *curpeers = peers;
6572
6573 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6574 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6575 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006576 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006577 break;
6578 }
6579 }
6580
6581 if (!curpeers) {
6582 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6583 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006584 free((void *)curproxy->table.peers.name);
6585 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006586 cfgerr++;
6587 }
6588 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006589 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6590 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006591 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006592 cfgerr++;
6593 }
6594 }
6595
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006596 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006597 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006598 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6599 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6600 "proxy", curproxy->id);
6601 cfgerr++;
6602 goto out_uri_auth_compat;
6603 }
6604
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006605 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006606 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006607 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006608 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006609
Willy Tarreau95fa4692010-02-01 13:05:50 +01006610 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6611 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006612
6613 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006614 uri_auth_compat_req[i++] = "realm";
6615 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6616 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006617
Willy Tarreau95fa4692010-02-01 13:05:50 +01006618 uri_auth_compat_req[i++] = "unless";
6619 uri_auth_compat_req[i++] = "{";
6620 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6621 uri_auth_compat_req[i++] = "}";
6622 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006623
Willy Tarreauff011f22011-01-06 17:51:27 +01006624 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6625 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006626 cfgerr++;
6627 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006628 }
6629
Willy Tarreauff011f22011-01-06 17:51:27 +01006630 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006631
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006632 if (curproxy->uri_auth->auth_realm) {
6633 free(curproxy->uri_auth->auth_realm);
6634 curproxy->uri_auth->auth_realm = NULL;
6635 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006636
6637 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006638 }
6639out_uri_auth_compat:
6640
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006641 /* compile the log format */
6642 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006643 if (curproxy->conf.logformat_string != default_http_log_format &&
6644 curproxy->conf.logformat_string != default_tcp_log_format &&
6645 curproxy->conf.logformat_string != clf_http_log_format)
6646 free(curproxy->conf.logformat_string);
6647 curproxy->conf.logformat_string = NULL;
6648 free(curproxy->conf.lfs_file);
6649 curproxy->conf.lfs_file = NULL;
6650 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006651 }
6652
Willy Tarreau62a61232013-04-12 18:13:46 +02006653 if (curproxy->conf.logformat_string) {
6654 curproxy->conf.args.ctx = ARGC_LOG;
6655 curproxy->conf.args.file = curproxy->conf.lfs_file;
6656 curproxy->conf.args.line = curproxy->conf.lfs_line;
6657 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006658 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006659 curproxy->conf.args.file = NULL;
6660 curproxy->conf.args.line = 0;
6661 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006662
Willy Tarreau62a61232013-04-12 18:13:46 +02006663 if (curproxy->conf.uniqueid_format_string) {
6664 curproxy->conf.args.ctx = ARGC_UIF;
6665 curproxy->conf.args.file = curproxy->conf.uif_file;
6666 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006667 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006668 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6669 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006670 curproxy->conf.args.file = NULL;
6671 curproxy->conf.args.line = 0;
6672 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006673
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006674 /* only now we can check if some args remain unresolved.
6675 * This must be done after the users and groups resolution.
6676 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006677 cfgerr += smp_resolve_args(curproxy);
6678 if (!cfgerr)
6679 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006680
Willy Tarreau2738a142006-07-08 17:28:09 +02006681 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006682 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006683 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006684 (!curproxy->timeout.connect ||
6685 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006686 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006687 " | While not properly invalid, you will certainly encounter various problems\n"
6688 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006689 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006690 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006691 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006692 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006693
Willy Tarreau1fa31262007-12-03 00:36:16 +01006694 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6695 * We must still support older configurations, so let's find out whether those
6696 * parameters have been set or must be copied from contimeouts.
6697 */
6698 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006699 if (!curproxy->timeout.tarpit ||
6700 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006701 /* tarpit timeout not set. We search in the following order:
6702 * default.tarpit, curr.connect, default.connect.
6703 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006704 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006705 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006706 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006707 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006708 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006709 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006710 }
6711 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006712 (!curproxy->timeout.queue ||
6713 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006714 /* queue timeout not set. We search in the following order:
6715 * default.queue, curr.connect, default.connect.
6716 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006717 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006718 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006719 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006720 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006721 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006722 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006723 }
6724 }
6725
Willy Tarreau1620ec32011-08-06 17:05:02 +02006726 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006727 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6728 curproxy->check_req = (char *)malloc(curproxy->check_len);
6729 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006730 }
6731
Willy Tarreau215663d2014-06-13 18:30:23 +02006732 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6733 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6734 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6735 proxy_type_str(curproxy), curproxy->id);
6736 err_code |= ERR_WARN;
6737 }
6738
Willy Tarreau193b8c62012-11-22 00:17:38 +01006739 /* ensure that cookie capture length is not too large */
6740 if (curproxy->capture_len >= global.tune.cookie_len) {
6741 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6742 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6743 err_code |= ERR_WARN;
6744 curproxy->capture_len = global.tune.cookie_len - 1;
6745 }
6746
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006747 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006748 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006749 curproxy->req_cap_pool = create_pool("ptrcap",
6750 curproxy->nb_req_cap * sizeof(char *),
6751 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006752 }
6753
6754 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006755 curproxy->rsp_cap_pool = create_pool("ptrcap",
6756 curproxy->nb_rsp_cap * sizeof(char *),
6757 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006758 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006759
Willy Tarreaubaaee002006-06-26 02:48:02 +02006760 /* first, we will invert the servers list order */
6761 newsrv = NULL;
6762 while (curproxy->srv) {
6763 struct server *next;
6764
6765 next = curproxy->srv->next;
6766 curproxy->srv->next = newsrv;
6767 newsrv = curproxy->srv;
6768 if (!next)
6769 break;
6770 curproxy->srv = next;
6771 }
6772
Willy Tarreau17edc812014-01-03 12:14:34 +01006773 /* Check that no server name conflicts. This causes trouble in the stats.
6774 * We only emit a warning for the first conflict affecting each server,
6775 * in order to avoid combinatory explosion if all servers have the same
6776 * name. We do that only for servers which do not have an explicit ID,
6777 * because these IDs were made also for distinguishing them and we don't
6778 * want to annoy people who correctly manage them.
6779 */
6780 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6781 struct server *other_srv;
6782
6783 if (newsrv->puid)
6784 continue;
6785
6786 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6787 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6788 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6789 newsrv->conf.file, newsrv->conf.line,
6790 proxy_type_str(curproxy), curproxy->id,
6791 newsrv->id, other_srv->conf.line);
6792 break;
6793 }
6794 }
6795 }
6796
Willy Tarreaudd701652010-05-25 23:03:02 +02006797 /* assign automatic UIDs to servers which don't have one yet */
6798 next_id = 1;
6799 newsrv = curproxy->srv;
6800 while (newsrv != NULL) {
6801 if (!newsrv->puid) {
6802 /* server ID not set, use automatic numbering with first
6803 * spare entry starting with next_svid.
6804 */
6805 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6806 newsrv->conf.id.key = newsrv->puid = next_id;
6807 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6808 }
6809 next_id++;
6810 newsrv = newsrv->next;
6811 }
6812
Willy Tarreau20697042007-11-15 23:26:18 +01006813 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006814 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006815
Willy Tarreau62c3be22012-01-20 13:12:32 +01006816 /*
6817 * If this server supports a maxconn parameter, it needs a dedicated
6818 * tasks to fill the emptied slots when a connection leaves.
6819 * Also, resolve deferred tracking dependency if needed.
6820 */
6821 newsrv = curproxy->srv;
6822 while (newsrv != NULL) {
6823 if (newsrv->minconn > newsrv->maxconn) {
6824 /* Only 'minconn' was specified, or it was higher than or equal
6825 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6826 * this will avoid further useless expensive computations.
6827 */
6828 newsrv->maxconn = newsrv->minconn;
6829 } else if (newsrv->maxconn && !newsrv->minconn) {
6830 /* minconn was not specified, so we set it to maxconn */
6831 newsrv->minconn = newsrv->maxconn;
6832 }
6833
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006834#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006835 if (newsrv->use_ssl || newsrv->check.use_ssl)
6836 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006837#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006838
Willy Tarreau2f075e92013-12-03 11:11:34 +01006839 /* set the check type on the server */
6840 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6841
Willy Tarreau62c3be22012-01-20 13:12:32 +01006842 if (newsrv->trackit) {
6843 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006844 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006845 char *pname, *sname;
6846
6847 pname = newsrv->trackit;
6848 sname = strrchr(pname, '/');
6849
6850 if (sname)
6851 *sname++ = '\0';
6852 else {
6853 sname = pname;
6854 pname = NULL;
6855 }
6856
6857 if (pname) {
6858 px = findproxy(pname, PR_CAP_BE);
6859 if (!px) {
6860 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6861 proxy_type_str(curproxy), curproxy->id,
6862 newsrv->id, pname);
6863 cfgerr++;
6864 goto next_srv;
6865 }
6866 } else
6867 px = curproxy;
6868
6869 srv = findserver(px, sname);
6870 if (!srv) {
6871 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6872 proxy_type_str(curproxy), curproxy->id,
6873 newsrv->id, sname);
6874 cfgerr++;
6875 goto next_srv;
6876 }
6877
Willy Tarreau32091232014-05-16 13:52:00 +02006878 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6879 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6880 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006881 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006882 "tracking as it does not have any check nor agent enabled.\n",
6883 proxy_type_str(curproxy), curproxy->id,
6884 newsrv->id, px->id, srv->id);
6885 cfgerr++;
6886 goto next_srv;
6887 }
6888
6889 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6890
6891 if (loop) {
6892 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6893 "belongs to a tracking chain looping back to %s/%s.\n",
6894 proxy_type_str(curproxy), curproxy->id,
6895 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006896 cfgerr++;
6897 goto next_srv;
6898 }
6899
6900 if (curproxy != px &&
6901 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6902 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6903 "tracking: disable-on-404 option inconsistency.\n",
6904 proxy_type_str(curproxy), curproxy->id,
6905 newsrv->id, px->id, srv->id);
6906 cfgerr++;
6907 goto next_srv;
6908 }
6909
6910 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006911 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006912 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006913 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006914 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006915 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006916 }
6917
6918 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006919 newsrv->tracknext = srv->trackers;
6920 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006921
6922 free(newsrv->trackit);
6923 newsrv->trackit = NULL;
6924 }
6925 next_srv:
6926 newsrv = newsrv->next;
6927 }
6928
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006929 /* We have to initialize the server lookup mechanism depending
6930 * on what LB algorithm was choosen.
6931 */
6932
6933 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6934 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6935 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006936 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6937 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6938 init_server_map(curproxy);
6939 } else {
6940 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6941 fwrr_init_server_groups(curproxy);
6942 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006943 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006944
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006945 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006946 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6947 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6948 fwlc_init_server_tree(curproxy);
6949 } else {
6950 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6951 fas_init_server_tree(curproxy);
6952 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006953 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006954
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006955 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006956 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6957 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6958 chash_init_server_tree(curproxy);
6959 } else {
6960 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6961 init_server_map(curproxy);
6962 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006963 break;
6964 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006965
6966 if (curproxy->options & PR_O_LOGASAP)
6967 curproxy->to_log &= ~LW_BYTES;
6968
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006969 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006970 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006971 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6972 proxy_type_str(curproxy), curproxy->id);
6973 err_code |= ERR_WARN;
6974 }
6975
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006976 if (curproxy->mode != PR_MODE_HTTP) {
6977 int optnum;
6978
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006979 if (curproxy->uri_auth) {
6980 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6981 proxy_type_str(curproxy), curproxy->id);
6982 err_code |= ERR_WARN;
6983 curproxy->uri_auth = NULL;
6984 }
6985
Willy Tarreau87cf5142011-08-19 22:57:24 +02006986 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006987 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6988 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6989 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006990 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006991 }
6992
6993 if (curproxy->options & PR_O_ORGTO) {
6994 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6995 "originalto", proxy_type_str(curproxy), curproxy->id);
6996 err_code |= ERR_WARN;
6997 curproxy->options &= ~PR_O_ORGTO;
6998 }
6999
7000 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7001 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7002 (curproxy->cap & cfg_opts[optnum].cap) &&
7003 (curproxy->options & cfg_opts[optnum].val)) {
7004 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7005 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7006 err_code |= ERR_WARN;
7007 curproxy->options &= ~cfg_opts[optnum].val;
7008 }
7009 }
7010
7011 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7012 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7013 (curproxy->cap & cfg_opts2[optnum].cap) &&
7014 (curproxy->options2 & cfg_opts2[optnum].val)) {
7015 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7016 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7017 err_code |= ERR_WARN;
7018 curproxy->options2 &= ~cfg_opts2[optnum].val;
7019 }
7020 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007021
Pieter Baauwd551fb52013-05-08 22:49:23 +02007022#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007023 if (curproxy->conn_src.bind_hdr_occ) {
7024 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007025 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007026 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007027 err_code |= ERR_WARN;
7028 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007029#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007030 }
7031
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007033 * ensure that we're not cross-dressing a TCP server into HTTP.
7034 */
7035 newsrv = curproxy->srv;
7036 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007037 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007038 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7039 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007040 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007041 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007042
Willy Tarreau0cec3312011-10-31 13:49:26 +01007043 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7044 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7045 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7046 err_code |= ERR_WARN;
7047 }
7048
Willy Tarreauc93cd162014-05-13 15:54:22 +02007049 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007050 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7051 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7052 err_code |= ERR_WARN;
7053 }
7054
Pieter Baauwd551fb52013-05-08 22:49:23 +02007055#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007056 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7057 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007058 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 +01007059 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007060 err_code |= ERR_WARN;
7061 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007062#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007063 newsrv = newsrv->next;
7064 }
7065
Willy Tarreauc1a21672009-08-16 22:37:44 +02007066 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007067 if (!curproxy->accept)
7068 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007069
Willy Tarreauc1a21672009-08-16 22:37:44 +02007070 if (curproxy->tcp_req.inspect_delay ||
7071 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007072 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007073
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007074 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007075 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007076 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007077 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007078
7079 /* both TCP and HTTP must check switching rules */
7080 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7081 }
7082
7083 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007084 if (curproxy->tcp_req.inspect_delay ||
7085 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7086 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7087
Emeric Brun97679e72010-09-23 17:56:44 +02007088 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7089 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7090
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007091 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007092 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007093 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007094 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007095
7096 /* If the backend does requires RDP cookie persistence, we have to
7097 * enable the corresponding analyser.
7098 */
7099 if (curproxy->options2 & PR_O2_RDPC_PRST)
7100 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7101 }
7102
Emeric Brunc52962f2012-11-15 18:28:02 +01007103#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007104 /* Configure SSL for each bind line.
7105 * Note: if configuration fails at some point, the ->ctx member
7106 * remains NULL so that listeners can later detach.
7107 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007108 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007109 int alloc_ctx;
7110
Emeric Brunc52962f2012-11-15 18:28:02 +01007111 if (!bind_conf->is_ssl) {
7112 if (bind_conf->default_ctx) {
7113 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7114 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7115 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007116 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007117 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007118 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007119 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007120 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007121 cfgerr++;
7122 continue;
7123 }
7124
Emeric Brun8dc60392014-05-09 13:52:00 +02007125 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007126 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007127 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7128 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");
7129 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007130 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007131 cfgerr++;
7132 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007133 }
7134
Emeric Brunfc0421f2012-09-07 17:30:07 +02007135 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007136 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007137 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007138#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007139
Willy Tarreaue6b98942007-10-29 01:09:36 +01007140 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007141 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007142 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007143 if (!listener->luid) {
7144 /* listener ID not set, use automatic numbering with first
7145 * spare entry starting with next_luid.
7146 */
7147 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7148 listener->conf.id.key = listener->luid = next_id;
7149 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007150 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007151 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007152
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007153 /* enable separate counters */
7154 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7155 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007156 if (!listener->name)
7157 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007158 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007159
Willy Tarreaue6b98942007-10-29 01:09:36 +01007160 if (curproxy->options & PR_O_TCP_NOLING)
7161 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007162 if (!listener->maxconn)
7163 listener->maxconn = curproxy->maxconn;
7164 if (!listener->backlog)
7165 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007166 if (!listener->maxaccept)
7167 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7168
7169 /* we want to have an optimal behaviour on single process mode to
7170 * maximize the work at once, but in multi-process we want to keep
7171 * some fairness between processes, so we target half of the max
7172 * number of events to be balanced over all the processes the proxy
7173 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7174 * used to disable the limit.
7175 */
7176 if (listener->maxaccept > 0) {
7177 if (nbproc > 1)
7178 listener->maxaccept = (listener->maxaccept + 1) / 2;
7179 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7180 }
7181
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007182 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007183 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007184 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007185 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007186
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007187 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7188 listener->options |= LI_O_TCP_RULES;
7189
Willy Tarreaude3041d2010-05-31 10:56:17 +02007190 if (curproxy->mon_mask.s_addr)
7191 listener->options |= LI_O_CHK_MONNET;
7192
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007193 /* smart accept mode is automatic in HTTP mode */
7194 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007195 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007196 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7197 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007198 }
7199
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007200 /* Release unused SSL configs */
7201 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7202 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007203 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007204#ifdef USE_OPENSSL
7205 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007206 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007207 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007208 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007209 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007210#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007211 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007212
Willy Tarreau102df612014-05-07 23:56:38 +02007213 if (nbproc > 1) {
7214 if (curproxy->uri_auth) {
7215 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7216 curproxy->id);
7217 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7218 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7219 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007220 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007221 }
Willy Tarreau102df612014-05-07 23:56:38 +02007222 if (curproxy->appsession_name) {
7223 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7224 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007225 }
Willy Tarreau102df612014-05-07 23:56:38 +02007226 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7227 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7228 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007229 }
7230 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007231
7232 /* create the task associated with the proxy */
7233 curproxy->task = task_new();
7234 if (curproxy->task) {
7235 curproxy->task->context = curproxy;
7236 curproxy->task->process = manage_proxy;
7237 /* no need to queue, it will be done automatically if some
7238 * listener gets limited.
7239 */
7240 curproxy->task->expire = TICK_ETERNITY;
7241 } else {
7242 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7243 curproxy->id);
7244 cfgerr++;
7245 }
7246
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 curproxy = curproxy->next;
7248 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007249
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007250 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02007251 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02007252 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7253 unsigned long mask;
7254
7255 mask = nbits(global.nbproc);
7256 if (global.stats_fe->bind_proc)
7257 mask &= global.stats_fe->bind_proc;
7258
7259 if (bind_conf->bind_proc)
7260 mask &= bind_conf->bind_proc;
7261
7262 /* stop here if more than one process is used */
7263 if (popcount(mask) > 1)
7264 break;
7265 }
7266 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7267 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");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007268 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007269 }
7270
7271 /* automatically compute fullconn if not set. We must not do it in the
7272 * loop above because cross-references are not yet fully resolved.
7273 */
7274 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7275 /* If <fullconn> is not set, let's set it to 10% of the sum of
7276 * the possible incoming frontend's maxconns.
7277 */
7278 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7279 struct proxy *fe;
7280 int total = 0;
7281
7282 /* sum up the number of maxconns of frontends which
7283 * reference this backend at least once or which are
7284 * the same one ('listen').
7285 */
7286 for (fe = proxy; fe; fe = fe->next) {
7287 struct switching_rule *rule;
7288 struct hdr_exp *exp;
7289 int found = 0;
7290
7291 if (!(fe->cap & PR_CAP_FE))
7292 continue;
7293
7294 if (fe == curproxy) /* we're on a "listen" instance */
7295 found = 1;
7296
7297 if (fe->defbe.be == curproxy) /* "default_backend" */
7298 found = 1;
7299
7300 /* check if a "use_backend" rule matches */
7301 if (!found) {
7302 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007303 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007304 found = 1;
7305 break;
7306 }
7307 }
7308 }
7309
7310 /* check if a "reqsetbe" rule matches */
7311 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7312 if (exp->action == ACT_SETBE &&
7313 (struct proxy *)exp->replace == curproxy) {
7314 found = 1;
7315 break;
7316 }
7317 }
7318
7319 /* now we've checked all possible ways to reference a backend
7320 * from a frontend.
7321 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007322 if (!found)
7323 continue;
7324 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007325 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007326 /* we have the sum of the maxconns in <total>. We only
7327 * keep 10% of that sum to set the default fullconn, with
7328 * a hard minimum of 1 (to avoid a divide by zero).
7329 */
7330 curproxy->fullconn = (total + 9) / 10;
7331 if (!curproxy->fullconn)
7332 curproxy->fullconn = 1;
7333 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007334 }
7335
Willy Tarreau056f5682010-06-06 15:51:11 +02007336 /* initialize stick-tables on backend capable proxies. This must not
7337 * be done earlier because the data size may be discovered while parsing
7338 * other proxies.
7339 */
Godbach9703e662013-12-11 21:11:41 +08007340 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007341 if (curproxy->state == PR_STSTOPPED)
7342 continue;
7343
Godbach9703e662013-12-11 21:11:41 +08007344 if (!stktable_init(&curproxy->table)) {
7345 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7346 cfgerr++;
7347 }
7348 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007349
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007350 /*
7351 * Recount currently required checks.
7352 */
7353
7354 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7355 int optnum;
7356
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007357 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7358 if (curproxy->options & cfg_opts[optnum].val)
7359 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007360
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007361 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7362 if (curproxy->options2 & cfg_opts2[optnum].val)
7363 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007364 }
7365
Willy Tarreau122541c2011-09-07 21:24:49 +02007366 if (peers) {
7367 struct peers *curpeers = peers, **last;
7368 struct peer *p, *pb;
7369
7370 /* Remove all peers sections which don't have a valid listener.
7371 * This can happen when a peers section is never referenced and
7372 * does not contain a local peer.
7373 */
7374 last = &peers;
7375 while (*last) {
7376 curpeers = *last;
7377 if (curpeers->peers_fe) {
7378 last = &curpeers->next;
7379 continue;
7380 }
7381
7382 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7383 curpeers->id, localpeer);
7384
7385 p = curpeers->remote;
7386 while (p) {
7387 pb = p->next;
7388 free(p->id);
7389 free(p);
7390 p = pb;
7391 }
7392
7393 /* Destroy and unlink this curpeers section.
7394 * Note: curpeers is backed up into *last.
7395 */
7396 free(curpeers->id);
7397 curpeers = curpeers->next;
7398 free(*last);
7399 *last = curpeers;
7400 }
7401 }
7402
Willy Tarreau34eb6712011-10-24 18:15:04 +02007403 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007404 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007405 MEM_F_SHARED);
7406
Willy Tarreaubb925012009-07-23 13:36:36 +02007407 if (cfgerr > 0)
7408 err_code |= ERR_ALERT | ERR_FATAL;
7409 out:
7410 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007411}
7412
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007413/*
7414 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7415 * parsing sessions.
7416 */
7417void cfg_register_keywords(struct cfg_kw_list *kwl)
7418{
7419 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7420}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007421
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007422/*
7423 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7424 */
7425void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7426{
7427 LIST_DEL(&kwl->list);
7428 LIST_INIT(&kwl->list);
7429}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007430
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007431/* this function register new section in the haproxy configuration file.
7432 * <section_name> is the name of this new section and <section_parser>
7433 * is the called parser. If two section declaration have the same name,
7434 * only the first declared is used.
7435 */
7436int cfg_register_section(char *section_name,
7437 int (*section_parser)(const char *, int, char **, int))
7438{
7439 struct cfg_section *cs;
7440
7441 cs = calloc(1, sizeof(*cs));
7442 if (!cs) {
7443 Alert("register section '%s': out of memory.\n", section_name);
7444 return 0;
7445 }
7446
7447 cs->section_name = section_name;
7448 cs->section_parser = section_parser;
7449
7450 LIST_ADDQ(&sections, &cs->list);
7451
7452 return 1;
7453}
7454
Willy Tarreaubaaee002006-06-26 02:48:02 +02007455/*
7456 * Local variables:
7457 * c-indent-level: 8
7458 * c-basic-offset: 8
7459 * End:
7460 */