blob: 40d20ab0a1ee9198d1216bb790471463fc52b0c9 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté2c8d7002014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy 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 Tarreau8b3c8082014-09-16 15:39:51 +0200320/* Report a warning if a rule is placed after a 'tcp-request content' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
323int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
324{
325 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
Willy Tarreau61d18892009-03-31 10:49:21 +0200333/* Report a warning if a rule is placed after a 'block' rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200338 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
Willy Tarreau5002f572014-04-23 01:32:02 +0200346/* Report a warning if a rule is placed after an 'http_request' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
349int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
350{
351 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
Willy Tarreau61d18892009-03-31 10:49:21 +0200359/* Report a warning if a rule is placed after a reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' 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 reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' 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 redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
Willy Tarreauee445d92014-04-23 01:39:04 +0200411/* Report a warning if a rule is placed after a 'use-server' rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
414int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
415{
416 if (!LIST_ISEMPTY(&proxy->server_rules)) {
417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200424/* report a warning if a "tcp request connection" rule is dangerously placed */
425int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
426{
427 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
428 warnif_rule_after_block(proxy, file, line, arg) ||
429 warnif_rule_after_http_req(proxy, file, line, arg) ||
430 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
431 warnif_rule_after_reqadd(proxy, file, line, arg) ||
432 warnif_rule_after_redirect(proxy, file, line, arg) ||
433 warnif_rule_after_use_backend(proxy, file, line, arg) ||
434 warnif_rule_after_use_server(proxy, file, line, arg);
435}
436
437/* report a warning if a "tcp request content" rule is dangerously placed */
438int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
439{
440 return warnif_rule_after_block(proxy, file, line, arg) ||
441 warnif_rule_after_http_req(proxy, file, line, arg) ||
442 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
443 warnif_rule_after_reqadd(proxy, file, line, arg) ||
444 warnif_rule_after_redirect(proxy, file, line, arg) ||
445 warnif_rule_after_use_backend(proxy, file, line, arg) ||
446 warnif_rule_after_use_server(proxy, file, line, arg);
447}
448
Willy Tarreau61d18892009-03-31 10:49:21 +0200449/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
Willy Tarreau5002f572014-04-23 01:32:02 +0200452 return warnif_rule_after_http_req(proxy, file, line, arg) ||
453 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
454 warnif_rule_after_reqadd(proxy, file, line, arg) ||
455 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200456 warnif_rule_after_use_backend(proxy, file, line, arg) ||
457 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200458}
459
460/* report a warning if an http-request rule is dangerously placed */
461int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
462{
Willy Tarreau61d18892009-03-31 10:49:21 +0200463 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
464 warnif_rule_after_reqadd(proxy, file, line, arg) ||
465 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200466 warnif_rule_after_use_backend(proxy, file, line, arg) ||
467 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200468}
469
470/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100471int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200472{
473 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
474 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200475 warnif_rule_after_use_backend(proxy, file, line, arg) ||
476 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200477}
478
479/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100480int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200481{
482 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200483 warnif_rule_after_use_backend(proxy, file, line, arg) ||
484 warnif_rule_after_use_server(proxy, file, line, arg);
485}
486
487/* report a warning if a redirect rule is dangerously placed */
488int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
489{
490 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
491 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200492}
493
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100494/* Report it if a request ACL condition uses some keywords that are incompatible
495 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
496 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
497 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100498 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100499static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100500{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100501 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200502 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100503
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100504 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100505 return 0;
506
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100507 acl = acl_cond_conflicts(cond, where);
508 if (acl) {
509 if (acl->name && *acl->name)
510 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
511 file, line, acl->name, sample_ckp_names(where));
512 else
513 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 +0200514 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100515 return ERR_WARN;
516 }
517 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100518 return 0;
519
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100520 if (acl->name && *acl->name)
521 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200522 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100523 else
524 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200525 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100526 return ERR_WARN;
527}
528
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 * parse a line in a <global> section. Returns the error code, 0 if OK, or
531 * any combination of :
532 * - ERR_ABORT: must abort ASAP
533 * - ERR_FATAL: we can continue parsing but not start the service
534 * - ERR_WARN: a warning has been emitted
535 * - ERR_ALERT: an alert has been emitted
536 * Only the two first ones can stop processing, the two others are just
537 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200539int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540{
Willy Tarreau058e9072009-07-20 09:30:05 +0200541 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200542 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543
544 if (!strcmp(args[0], "global")) { /* new section */
545 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200548 else if (!strcmp(args[0], "ca-base")) {
549#ifdef USE_OPENSSL
550 if (global.ca_base != NULL) {
551 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT;
553 goto out;
554 }
555 if (*(args[1]) == 0) {
556 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT | ERR_FATAL;
558 goto out;
559 }
560 global.ca_base = strdup(args[1]);
561#else
562 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
563 err_code |= ERR_ALERT | ERR_FATAL;
564 goto out;
565#endif
566 }
567 else if (!strcmp(args[0], "crt-base")) {
568#ifdef USE_OPENSSL
569 if (global.crt_base != NULL) {
570 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT;
572 goto out;
573 }
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579 global.crt_base = strdup(args[1]);
580#else
581 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584#endif
585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 else if (!strcmp(args[0], "daemon")) {
587 global.mode |= MODE_DAEMON;
588 }
589 else if (!strcmp(args[0], "debug")) {
590 global.mode |= MODE_DEBUG;
591 }
592 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100593 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200595 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100596 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100599 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100601 else if (!strcmp(args[0], "nosplice")) {
602 global.tune.options &= ~GTUNE_USE_SPLICE;
603 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200604 else if (!strcmp(args[0], "nogetaddrinfo")) {
605 global.tune.options &= ~GTUNE_USE_GAI;
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 else if (!strcmp(args[0], "quiet")) {
608 global.mode |= MODE_QUIET;
609 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200610 else if (!strcmp(args[0], "tune.maxpollevents")) {
611 if (global.tune.maxpollevents != 0) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200613 err_code |= ERR_ALERT;
614 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200620 }
621 global.tune.maxpollevents = atol(args[1]);
622 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100623 else if (!strcmp(args[0], "tune.maxaccept")) {
624 if (global.tune.maxaccept != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT;
627 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100633 }
634 global.tune.maxaccept = atol(args[1]);
635 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200636 else if (!strcmp(args[0], "tune.chksize")) {
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.chksize = atol(args[1]);
643 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200644#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200645 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
646 global.tune.sslprivatecache = 1;
647 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100648 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
653 }
654 global.tune.sslcachesize = atol(args[1]);
655 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100656 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
657 unsigned int ssllifetime;
658 const char *res;
659
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
664 }
665
666 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
667 if (res) {
668 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
669 file, linenum, *res, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673
674 global.tune.ssllifetime = ssllifetime;
675 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100676 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.ssl_max_record = atol(args[1]);
683 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200684 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.ssl_default_dh_param = atol(args[1]);
691 if (global.tune.ssl_default_dh_param < 1024) {
692 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200697#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200698 else if (!strcmp(args[0], "tune.bufsize")) {
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.bufsize = atol(args[1]);
705 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
706 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100707 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100708 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200709 }
710 else if (!strcmp(args[0], "tune.maxrewrite")) {
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 global.tune.maxrewrite = atol(args[1]);
717 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
718 global.tune.maxrewrite = global.tune.bufsize / 2;
719 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100720 else if (!strcmp(args[0], "tune.idletimer")) {
721 unsigned int idle;
722 const char *res;
723
724 if (*(args[1]) == 0) {
725 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729
730 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
731 if (res) {
732 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
733 file, linenum, *res, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 if (idle > 65535) {
739 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.idle_timer = idle;
744 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100745 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
746 if (global.tune.client_rcvbuf != 0) {
747 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT;
749 goto out;
750 }
751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.client_rcvbuf = atol(args[1]);
757 }
758 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
759 if (global.tune.server_rcvbuf != 0) {
760 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
761 err_code |= ERR_ALERT;
762 goto out;
763 }
764 if (*(args[1]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 global.tune.server_rcvbuf = atol(args[1]);
770 }
771 else if (!strcmp(args[0], "tune.sndbuf.client")) {
772 if (global.tune.client_sndbuf != 0) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT;
775 goto out;
776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.client_sndbuf = atol(args[1]);
783 }
784 else if (!strcmp(args[0], "tune.sndbuf.server")) {
785 if (global.tune.server_sndbuf != 0) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT;
788 goto out;
789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795 global.tune.server_sndbuf = atol(args[1]);
796 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200797 else if (!strcmp(args[0], "tune.pipesize")) {
798 if (*(args[1]) == 0) {
799 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803 global.tune.pipesize = atol(args[1]);
804 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100805 else if (!strcmp(args[0], "tune.http.cookielen")) {
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811 global.tune.cookie_len = atol(args[1]) + 1;
812 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200813 else if (!strcmp(args[0], "tune.http.maxhdr")) {
814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.max_http_hdr = atol(args[1]);
820 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100821 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
822#ifdef USE_ZLIB
823 if (*args[1]) {
824 global.tune.zlibmemlevel = atoi(args[1]);
825 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
826 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
827 file, linenum, args[0]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 } else {
832 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
833 file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837#else
838 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841#endif
842 }
843 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
844#ifdef USE_ZLIB
845 if (*args[1]) {
846 global.tune.zlibwindowsize = atoi(args[1]);
847 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
848 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
849 file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
853 } else {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859#else
860 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863#endif
864 }
William Lallemandf3747832012-11-09 12:33:10 +0100865 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
866 if (*args[1]) {
867 global.tune.comp_maxlevel = atoi(args[1]);
868 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
869 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
870 file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 } else {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881 else if (!strcmp(args[0], "uid")) {
882 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200883 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200884 err_code |= ERR_ALERT;
885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 }
887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 }
892 global.uid = atol(args[1]);
893 }
894 else if (!strcmp(args[0], "gid")) {
895 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200896 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200897 err_code |= ERR_ALERT;
898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899 }
900 if (*(args[1]) == 0) {
901 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905 global.gid = atol(args[1]);
906 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200907 /* user/group name handling */
908 else if (!strcmp(args[0], "user")) {
909 struct passwd *ha_user;
910 if (global.uid != 0) {
911 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
913 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200914 }
915 errno = 0;
916 ha_user = getpwnam(args[1]);
917 if (ha_user != NULL) {
918 global.uid = (int)ha_user->pw_uid;
919 }
920 else {
921 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 +0200922 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200923 }
924 }
925 else if (!strcmp(args[0], "group")) {
926 struct group *ha_group;
927 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200928 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT;
930 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200931 }
932 errno = 0;
933 ha_group = getgrnam(args[1]);
934 if (ha_group != NULL) {
935 global.gid = (int)ha_group->gr_gid;
936 }
937 else {
938 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 +0200939 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200940 }
941 }
942 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
949 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100950 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
951 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
952 file, linenum, args[0], LONGBITS, global.nbproc);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 }
957 else if (!strcmp(args[0], "maxconn")) {
958 if (global.maxconn != 0) {
959 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
968 global.maxconn = atol(args[1]);
969#ifdef SYSTEM_MAXCONN
970 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
971 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);
972 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 }
975#endif /* SYSTEM_MAXCONN */
976 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200977 else if (!strcmp(args[0], "maxsslconn")) {
978#ifdef USE_OPENSSL
979 if (*(args[1]) == 0) {
980 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
983 }
984 global.maxsslconn = atol(args[1]);
985#else
Emeric Brun0914df82012-10-02 18:45:42 +0200986 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200989#endif
990 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100991 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
992#ifdef USE_OPENSSL
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
998 free(global.listen_default_ciphers);
999 global.listen_default_ciphers = strdup(args[1]);
1000#else
1001 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
1004#endif
1005 }
1006 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1007#ifdef USE_OPENSSL
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 free(global.connect_default_ciphers);
1014 global.connect_default_ciphers = strdup(args[1]);
1015#else
1016 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
1019#endif
1020 }
Emeric Brun850efd52014-01-29 12:24:34 +01001021 else if (!strcmp(args[0], "ssl-server-verify")) {
1022 if (*(args[1]) == 0) {
1023 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
1026 }
1027 if (strcmp(args[1],"none") == 0)
1028 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1029 else if (strcmp(args[1],"required") == 0)
1030 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1031 else {
1032 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001037 else if (!strcmp(args[0], "maxconnrate")) {
1038 if (global.cps_lim != 0) {
1039 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1040 err_code |= ERR_ALERT;
1041 goto out;
1042 }
1043 if (*(args[1]) == 0) {
1044 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 global.cps_lim = atol(args[1]);
1049 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001050 else if (!strcmp(args[0], "maxsessrate")) {
1051 if (global.sps_lim != 0) {
1052 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1053 err_code |= ERR_ALERT;
1054 goto out;
1055 }
1056 if (*(args[1]) == 0) {
1057 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060 }
1061 global.sps_lim = atol(args[1]);
1062 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001063 else if (!strcmp(args[0], "maxsslrate")) {
1064 if (global.ssl_lim != 0) {
1065 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT;
1067 goto out;
1068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074 global.ssl_lim = atol(args[1]);
1075 }
William Lallemandd85f9172012-11-09 17:05:39 +01001076 else if (!strcmp(args[0], "maxcomprate")) {
1077 if (*(args[1]) == 0) {
1078 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
1081 }
1082 global.comp_rate_lim = atoi(args[1]) * 1024;
1083 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001084 else if (!strcmp(args[0], "maxpipes")) {
1085 if (global.maxpipes != 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 Tarreau3ec79b92009-01-18 20:39:42 +01001089 }
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 Tarreau3ec79b92009-01-18 20:39:42 +01001094 }
1095 global.maxpipes = atol(args[1]);
1096 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001097 else if (!strcmp(args[0], "maxzlibmem")) {
1098 if (*(args[1]) == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto out;
1102 }
William Lallemande3a7d992012-11-20 11:25:20 +01001103 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001104 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001105 else if (!strcmp(args[0], "maxcompcpuusage")) {
1106 if (*(args[1]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
1110 }
1111 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001112 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001113 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117}
1118
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 else if (!strcmp(args[0], "ulimit-n")) {
1120 if (global.rlimit_nofile != 0) {
1121 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT;
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 }
1125 if (*(args[1]) == 0) {
1126 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 }
1130 global.rlimit_nofile = atol(args[1]);
1131 }
1132 else if (!strcmp(args[0], "chroot")) {
1133 if (global.chroot != NULL) {
1134 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138 if (*(args[1]) == 0) {
1139 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001142 }
1143 global.chroot = strdup(args[1]);
1144 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001145 else if (!strcmp(args[0], "description")) {
1146 int i, len=0;
1147 char *d;
1148
1149 if (!*args[1]) {
1150 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1151 file, linenum, args[0]);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
1154 }
1155
Willy Tarreau348acfe2014-04-14 15:00:39 +02001156 for (i = 1; *args[i]; i++)
1157 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001158
1159 if (global.desc)
1160 free(global.desc);
1161
1162 global.desc = d = (char *)calloc(1, len);
1163
Willy Tarreau348acfe2014-04-14 15:00:39 +02001164 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1165 for (i = 2; *args[i]; i++)
1166 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001167 }
1168 else if (!strcmp(args[0], "node")) {
1169 int i;
1170 char c;
1171
1172 for (i=0; args[1][i]; i++) {
1173 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001174 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1175 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001176 break;
1177 }
1178
1179 if (!i || args[1][i]) {
1180 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1181 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1182 file, linenum, args[0]);
1183 err_code |= ERR_ALERT | ERR_FATAL;
1184 goto out;
1185 }
1186
1187 if (global.node)
1188 free(global.node);
1189
1190 global.node = strdup(args[1]);
1191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192 else if (!strcmp(args[0], "pidfile")) {
1193 if (global.pidfile != NULL) {
1194 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001195 err_code |= ERR_ALERT;
1196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 }
1198 if (*(args[1]) == 0) {
1199 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203 global.pidfile = strdup(args[1]);
1204 }
Emeric Bruned760922010-10-22 17:59:25 +02001205 else if (!strcmp(args[0], "unix-bind")) {
1206 int cur_arg = 1;
1207 while (*(args[cur_arg])) {
1208 if (!strcmp(args[cur_arg], "prefix")) {
1209 if (global.unix_bind.prefix != NULL) {
1210 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1211 err_code |= ERR_ALERT;
1212 cur_arg += 2;
1213 continue;
1214 }
1215
1216 if (*(args[cur_arg+1]) == 0) {
1217 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1222 cur_arg += 2;
1223 continue;
1224 }
1225
1226 if (!strcmp(args[cur_arg], "mode")) {
1227
1228 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1229 cur_arg += 2;
1230 continue;
1231 }
1232
1233 if (!strcmp(args[cur_arg], "uid")) {
1234
1235 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1236 cur_arg += 2;
1237 continue;
1238 }
1239
1240 if (!strcmp(args[cur_arg], "gid")) {
1241
1242 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1243 cur_arg += 2;
1244 continue;
1245 }
1246
1247 if (!strcmp(args[cur_arg], "user")) {
1248 struct passwd *user;
1249
1250 user = getpwnam(args[cur_arg + 1]);
1251 if (!user) {
1252 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1253 file, linenum, args[0], args[cur_arg + 1 ]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257
1258 global.unix_bind.ux.uid = user->pw_uid;
1259 cur_arg += 2;
1260 continue;
1261 }
1262
1263 if (!strcmp(args[cur_arg], "group")) {
1264 struct group *group;
1265
1266 group = getgrnam(args[cur_arg + 1]);
1267 if (!group) {
1268 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1269 file, linenum, args[0], args[cur_arg + 1 ]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272 }
1273
1274 global.unix_bind.ux.gid = group->gr_gid;
1275 cur_arg += 2;
1276 continue;
1277 }
1278
Willy Tarreaub48f9582011-09-05 01:17:06 +02001279 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001280 file, linenum, args[0]);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284 }
William Lallemand0f99e342011-10-12 17:50:54 +02001285 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1286 /* delete previous herited or defined syslog servers */
1287 struct logsrv *back;
1288 struct logsrv *tmp;
1289
1290 if (*(args[1]) != 0) {
1291 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
1295
1296 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1297 LIST_DEL(&tmp->list);
1298 free(tmp);
1299 }
1300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001302 struct sockaddr_storage *sk;
1303 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001304 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001305 int arg = 0;
1306 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 if (*(args[1]) == 0 || *(args[2]) == 0) {
1309 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 }
William Lallemand0f99e342011-10-12 17:50:54 +02001313
1314 logsrv = calloc(1, sizeof(struct logsrv));
1315
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001316 /* just after the address, a length may be specified */
1317 if (strcmp(args[arg+2], "len") == 0) {
1318 len = atoi(args[arg+3]);
1319 if (len < 80 || len > 65535) {
1320 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1321 file, linenum, args[arg+3]);
1322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
1324 }
1325 logsrv->maxlen = len;
1326
1327 /* skip these two args */
1328 arg += 2;
1329 }
1330 else
1331 logsrv->maxlen = MAX_SYSLOG_LEN;
1332
1333 if (logsrv->maxlen > global.max_syslog_len) {
1334 global.max_syslog_len = logsrv->maxlen;
1335 logline = realloc(logline, global.max_syslog_len + 1);
1336 }
1337
1338 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001339 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001340 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001342 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
1344
William Lallemand0f99e342011-10-12 17:50:54 +02001345 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001346 if (*(args[arg+3])) {
1347 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001348 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001349 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001350 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001351 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 }
1353 }
1354
William Lallemand0f99e342011-10-12 17:50:54 +02001355 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001356 if (*(args[arg+4])) {
1357 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001358 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001359 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001361 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001362 }
1363 }
1364
Willy Tarreau902636f2013-03-10 19:44:48 +01001365 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001366 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001367 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001368 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001369 free(logsrv);
1370 goto out;
1371 }
1372 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001373
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001374 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001375 if (port1 != port2) {
1376 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1377 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001378 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001379 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001380 goto out;
1381 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001382
William Lallemand0f99e342011-10-12 17:50:54 +02001383 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001384 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001385 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387
William Lallemand0f99e342011-10-12 17:50:54 +02001388 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001389 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001390 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1391 char *name;
1392 int len;
1393
1394 if (global.log_send_hostname != NULL) {
1395 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1396 err_code |= ERR_ALERT;
1397 goto out;
1398 }
1399
1400 if (*(args[1]))
1401 name = args[1];
1402 else
1403 name = hostname;
1404
1405 len = strlen(name);
1406
1407 /* We'll add a space after the name to respect the log format */
1408 free(global.log_send_hostname);
1409 global.log_send_hostname = malloc(len + 2);
1410 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1411 }
Kevinm48936af2010-12-22 16:08:21 +00001412 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1413 if (*(args[1]) == 0) {
1414 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto out;
1417 }
1418 free(global.log_tag);
1419 global.log_tag = strdup(args[1]);
1420 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001421 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1422 if (global.spread_checks != 0) {
1423 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001424 err_code |= ERR_ALERT;
1425 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001426 }
1427 if (*(args[1]) == 0) {
1428 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001431 }
1432 global.spread_checks = atol(args[1]);
1433 if (global.spread_checks < 0 || global.spread_checks > 50) {
1434 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001435 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001438 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1439 const char *err;
1440 unsigned int val;
1441
1442
1443 if (*(args[1]) == 0) {
1444 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
1448
1449 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1450 if (err) {
1451 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1452 err_code |= ERR_ALERT | ERR_FATAL;
1453 }
1454 global.max_spread_checks = val;
1455 if (global.max_spread_checks < 0) {
1456 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1457 err_code |= ERR_ALERT | ERR_FATAL;
1458 }
1459 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001460 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1461#ifdef USE_CPU_AFFINITY
1462 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001463 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001464 unsigned long cpus = 0;
1465
1466 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001467 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001468 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001469 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001470 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001471 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001472 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001473 proc = atol(args[1]);
1474 if (proc >= 1 && proc <= LONGBITS)
1475 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001476 }
1477
1478 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001479 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",
1480 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
1483 }
1484
1485 cur_arg = 2;
1486 while (*args[cur_arg]) {
1487 unsigned int low, high;
1488
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001489 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001490 char *dash = strchr(args[cur_arg], '-');
1491
1492 low = high = str2uic(args[cur_arg]);
1493 if (dash)
1494 high = str2uic(dash + 1);
1495
1496 if (high < low) {
1497 unsigned int swap = low;
1498 low = high;
1499 high = swap;
1500 }
1501
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001502 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001503 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001504 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001505 err_code |= ERR_ALERT | ERR_FATAL;
1506 goto out;
1507 }
1508
1509 while (low <= high)
1510 cpus |= 1UL << low++;
1511 }
1512 else {
1513 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1514 file, linenum, args[0], args[cur_arg]);
1515 err_code |= ERR_ALERT | ERR_FATAL;
1516 goto out;
1517 }
1518 cur_arg++;
1519 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001520 for (i = 0; i < LONGBITS; i++)
1521 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001522 global.cpu_map[i] = cpus;
1523#else
1524 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1525 err_code |= ERR_ALERT | ERR_FATAL;
1526 goto out;
1527#endif
1528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001530 struct cfg_kw_list *kwl;
1531 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001532 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001533
1534 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1535 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1536 if (kwl->kw[index].section != CFG_GLOBAL)
1537 continue;
1538 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001539 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001540 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001541 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001542 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001543 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001544 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001545 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001546 err_code |= ERR_WARN;
1547 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001548 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001549 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001550 }
1551 }
1552 }
1553
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001555 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001557
Willy Tarreau058e9072009-07-20 09:30:05 +02001558 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001559 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001560 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561}
1562
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001563void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001565 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 defproxy.mode = PR_MODE_TCP;
1567 defproxy.state = PR_STNEW;
1568 defproxy.maxconn = cfg_maxpconn;
1569 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001570
Simon Horman66183002013-02-23 10:16:43 +09001571 defproxy.defsrv.check.inter = DEF_CHKINTR;
1572 defproxy.defsrv.check.fastinter = 0;
1573 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001574 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1575 defproxy.defsrv.agent.fastinter = 0;
1576 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001577 defproxy.defsrv.check.rise = DEF_RISETIME;
1578 defproxy.defsrv.check.fall = DEF_FALLTIME;
1579 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1580 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001581 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001582 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001583 defproxy.defsrv.maxqueue = 0;
1584 defproxy.defsrv.minconn = 0;
1585 defproxy.defsrv.maxconn = 0;
1586 defproxy.defsrv.slowstart = 0;
1587 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1588 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1589 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590}
1591
Willy Tarreauade5ec42010-01-28 19:33:49 +01001592
Willy Tarreau63af98d2014-05-18 08:11:41 +02001593/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1594 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1595 * ERR_FATAL in case of error.
1596 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001597static int create_cond_regex_rule(const char *file, int line,
1598 struct proxy *px, int dir, int action, int flags,
1599 const char *cmd, const char *reg, const char *repl,
1600 const char **cond_start)
1601{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001602 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001603 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001604 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001605 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001606 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001607 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001608 int cs;
1609 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001610
1611 if (px == &defproxy) {
1612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001613 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614 goto err;
1615 }
1616
1617 if (*reg == 0) {
1618 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001619 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001620 goto err;
1621 }
1622
1623 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001624 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001625
Willy Tarreau5321c422010-01-28 20:35:13 +01001626 if (cond_start &&
1627 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001628 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1629 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1630 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001631 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001632 goto err;
1633 }
1634 }
1635 else if (cond_start && **cond_start) {
1636 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1637 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001638 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001639 goto err;
1640 }
1641
Willy Tarreau63af98d2014-05-18 08:11:41 +02001642 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001643 (dir == SMP_OPT_DIR_REQ) ?
1644 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1645 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1646 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001647
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001648 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001649 if (!preg) {
1650 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001651 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001652 goto err;
1653 }
1654
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001655 cs = !(flags & REG_ICASE);
1656 cap = !(flags & REG_NOSUB);
1657 error = NULL;
1658 if (!regex_comp(reg, preg, cs, cap, &error)) {
1659 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1660 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001661 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001662 goto err;
1663 }
1664
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001665 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001666 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001667 if (repl && err) {
1668 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1669 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001670 ret_code |= ERR_ALERT | ERR_FATAL;
1671 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001672 }
1673
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001674 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001675 ret_code |= ERR_WARN;
1676
1677 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001678
Willy Tarreau63af98d2014-05-18 08:11:41 +02001679 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001680 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001681 err:
1682 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 free(errmsg);
1684 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001685}
1686
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001688 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001689 * Returns the error code, 0 if OK, or any combination of :
1690 * - ERR_ABORT: must abort ASAP
1691 * - ERR_FATAL: we can continue parsing but not start the service
1692 * - ERR_WARN: a warning has been emitted
1693 * - ERR_ALERT: an alert has been emitted
1694 * Only the two first ones can stop processing, the two others are just
1695 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001697int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1698{
1699 static struct peers *curpeers = NULL;
1700 struct peer *newpeer = NULL;
1701 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001702 struct bind_conf *bind_conf;
1703 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001704 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001705 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001706
1707 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001708 if (!*args[1]) {
1709 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001710 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001711 goto out;
1712 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001713
1714 err = invalid_char(args[1]);
1715 if (err) {
1716 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1717 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001718 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001719 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001720 }
1721
1722 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1723 /*
1724 * If there are two proxies with the same name only following
1725 * combinations are allowed:
1726 */
1727 if (strcmp(curpeers->id, args[1]) == 0) {
1728 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1729 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1730 err_code |= ERR_WARN;
1731 }
1732 }
1733
1734 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1735 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1736 err_code |= ERR_ALERT | ERR_ABORT;
1737 goto out;
1738 }
1739
1740 curpeers->next = peers;
1741 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001742 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001743 curpeers->conf.line = linenum;
1744 curpeers->last_change = now.tv_sec;
1745 curpeers->id = strdup(args[1]);
1746 }
1747 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001748 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001749 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001750 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001751
1752 if (!*args[2]) {
1753 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1754 file, linenum, args[0]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758
1759 err = invalid_char(args[1]);
1760 if (err) {
1761 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1762 file, linenum, *err, args[1]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
1765 }
1766
1767 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1768 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1769 err_code |= ERR_ALERT | ERR_ABORT;
1770 goto out;
1771 }
1772
1773 /* the peers are linked backwards first */
1774 curpeers->count++;
1775 newpeer->next = curpeers->remote;
1776 curpeers->remote = newpeer;
1777 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001778 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001779 newpeer->conf.line = linenum;
1780
1781 newpeer->last_change = now.tv_sec;
1782 newpeer->id = strdup(args[1]);
1783
Willy Tarreau902636f2013-03-10 19:44:48 +01001784 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001785 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001786 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001787 err_code |= ERR_ALERT | ERR_FATAL;
1788 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001789 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001790
1791 proto = protocol_by_family(sk->ss_family);
1792 if (!proto || !proto->connect) {
1793 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1794 file, linenum, args[0], args[1]);
1795 err_code |= ERR_ALERT | ERR_FATAL;
1796 goto out;
1797 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001798
1799 if (port1 != port2) {
1800 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1801 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804 }
1805
Willy Tarreau2aa38802013-02-20 19:20:59 +01001806 if (!port1) {
1807 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1808 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001812
Emeric Brun32da3c42010-09-23 18:39:19 +02001813 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001814 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001815 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001816 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001817
Emeric Brun32da3c42010-09-23 18:39:19 +02001818 if (strcmp(newpeer->id, localpeer) == 0) {
1819 /* Current is local peer, it define a frontend */
1820 newpeer->local = 1;
1821
1822 if (!curpeers->peers_fe) {
1823 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1824 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1825 err_code |= ERR_ALERT | ERR_ABORT;
1826 goto out;
1827 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001828
Willy Tarreau237250c2011-07-29 01:49:03 +02001829 init_new_proxy(curpeers->peers_fe);
1830 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001831
1832 curpeers->peers_fe->last_change = now.tv_sec;
1833 curpeers->peers_fe->id = strdup(args[1]);
1834 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001835 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001836 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1837 curpeers->peers_fe->timeout.connect = 5000;
1838 curpeers->peers_fe->accept = peer_accept;
1839 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001840 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1841 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001842
1843 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1844
Willy Tarreau902636f2013-03-10 19:44:48 +01001845 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1846 if (errmsg && *errmsg) {
1847 indent_msg(&errmsg, 2);
1848 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001849 }
1850 else
1851 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1852 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001853 err_code |= ERR_FATAL;
1854 goto out;
1855 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001856
1857 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001858 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001859 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1860 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1861 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1862 l->accept = session_accept;
1863 l->handler = process_session;
1864 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1865 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1866 global.maxsock += l->maxconn;
1867 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001868 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001869 else {
1870 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1871 file, linenum, args[0], args[1],
1872 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1873 err_code |= ERR_FATAL;
1874 goto out;
1875 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001876 }
1877 } /* neither "peer" nor "peers" */
1878 else if (*args[0] != 0) {
1879 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
1882 }
1883
1884out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001885 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001886 return err_code;
1887}
1888
Willy Tarreau3842f002009-06-14 11:39:52 +02001889int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890{
1891 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001892 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001893 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001894 int rc;
1895 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001896 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001897 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001898 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001899 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001900 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 if (!strcmp(args[0], "listen"))
1903 rc = PR_CAP_LISTEN;
1904 else if (!strcmp(args[0], "frontend"))
1905 rc = PR_CAP_FE | PR_CAP_RS;
1906 else if (!strcmp(args[0], "backend"))
1907 rc = PR_CAP_BE | PR_CAP_RS;
1908 else if (!strcmp(args[0], "ruleset"))
1909 rc = PR_CAP_RS;
1910 else
1911 rc = PR_CAP_NONE;
1912
1913 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001914 struct ebpt_node *node;
1915
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 if (!*args[1]) {
1917 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1918 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1919 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001920 err_code |= ERR_ALERT | ERR_ABORT;
1921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001923
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001924 err = invalid_char(args[1]);
1925 if (err) {
1926 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1927 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001928 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001929 }
1930
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001931 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1932 curproxy = container_of(node, struct proxy, conf.by_name);
1933
1934 if (strcmp(curproxy->id, args[1]) != 0)
1935 break;
1936
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001937 /*
1938 * If there are two proxies with the same name only following
1939 * combinations are allowed:
1940 *
1941 * listen backend frontend ruleset
1942 * listen - - - -
1943 * backend - - OK -
1944 * frontend - OK - -
1945 * ruleset - - - -
1946 */
1947
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001948 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1949 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001950 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1951 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1952 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001954 }
1955 }
1956
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1958 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_ALERT | ERR_ABORT;
1960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001962
Willy Tarreau97cb7802010-01-03 20:23:58 +01001963 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 curproxy->next = proxy;
1965 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001966 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1967 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001968 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001970 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001971 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972
1973 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001974 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001975 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001976
Willy Tarreau4348fad2012-09-20 16:48:07 +02001977 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1978
Willy Tarreau902636f2013-03-10 19:44:48 +01001979 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1980 if (errmsg && *errmsg) {
1981 indent_msg(&errmsg, 2);
1982 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001983 }
1984 else
1985 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1986 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_FATAL;
1988 goto out;
1989 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001990
Willy Tarreau4348fad2012-09-20 16:48:07 +02001991 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001992 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 }
1995
1996 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001997 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001998 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001999
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002002 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002003 curproxy->no_options = defproxy.no_options;
2004 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002005 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002006 curproxy->except_net = defproxy.except_net;
2007 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002008 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002009 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002011 if (defproxy.fwdfor_hdr_len) {
2012 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2013 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2014 }
2015
Willy Tarreaub86db342009-11-30 11:50:16 +01002016 if (defproxy.orgto_hdr_len) {
2017 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2018 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2019 }
2020
Mark Lamourinec2247f02012-01-04 13:02:01 -05002021 if (defproxy.server_id_hdr_len) {
2022 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2023 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2024 }
2025
Willy Tarreau977b8e42006-12-29 14:19:17 +01002026 if (curproxy->cap & PR_CAP_FE) {
2027 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002028 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002029 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002030
2031 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002032 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2033 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034
2035 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002039 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002040 curproxy->fullconn = defproxy.fullconn;
2041 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002042 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002044 if (defproxy.check_req) {
2045 curproxy->check_req = calloc(1, defproxy.check_len);
2046 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2047 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002050 if (defproxy.expect_str) {
2051 curproxy->expect_str = strdup(defproxy.expect_str);
2052 if (defproxy.expect_regex) {
2053 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002054 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2055 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002056 }
2057 }
2058
Willy Tarreau67402132012-05-31 20:40:20 +02002059 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002060 if (defproxy.cookie_name)
2061 curproxy->cookie_name = strdup(defproxy.cookie_name);
2062 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002063 if (defproxy.cookie_domain)
2064 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002065
Willy Tarreau31936852010-10-06 16:59:56 +02002066 if (defproxy.cookie_maxidle)
2067 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2068
2069 if (defproxy.cookie_maxlife)
2070 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2071
Emeric Brun647caf12009-06-30 17:57:00 +02002072 if (defproxy.rdp_cookie_name)
2073 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2074 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2075
Willy Tarreau01732802007-11-01 22:48:15 +01002076 if (defproxy.url_param_name)
2077 curproxy->url_param_name = strdup(defproxy.url_param_name);
2078 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002079
Benoitaffb4812009-03-25 13:02:10 +01002080 if (defproxy.hh_name)
2081 curproxy->hh_name = strdup(defproxy.hh_name);
2082 curproxy->hh_len = defproxy.hh_len;
2083 curproxy->hh_match_domain = defproxy.hh_match_domain;
2084
Willy Tarreauef9a3602012-12-08 22:29:20 +01002085 if (defproxy.conn_src.iface_name)
2086 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2087 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002088 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002089#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002090 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002091#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002094 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002095 if (defproxy.capture_name)
2096 curproxy->capture_name = strdup(defproxy.capture_name);
2097 curproxy->capture_namelen = defproxy.capture_namelen;
2098 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002102 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002103 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002104 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002105 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002106 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107 curproxy->mon_net = defproxy.mon_net;
2108 curproxy->mon_mask = defproxy.mon_mask;
2109 if (defproxy.monitor_uri)
2110 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2111 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002112 if (defproxy.defbe.name)
2113 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002114
2115 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002116 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2117 if (curproxy->conf.logformat_string &&
2118 curproxy->conf.logformat_string != default_http_log_format &&
2119 curproxy->conf.logformat_string != default_tcp_log_format &&
2120 curproxy->conf.logformat_string != clf_http_log_format)
2121 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2122
2123 if (defproxy.conf.lfs_file) {
2124 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2125 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2126 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002127 }
2128
2129 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002130 curproxy->timeout.connect = defproxy.timeout.connect;
2131 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002132 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002133 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002134 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002135 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002136 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002137 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002138 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002139 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002140 }
2141
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002143 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002144
2145 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002146 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002147 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002148 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002149 LIST_INIT(&node->list);
2150 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2151 }
2152
Willy Tarreau62a61232013-04-12 18:13:46 +02002153 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2154 if (curproxy->conf.uniqueid_format_string)
2155 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2156
2157 if (defproxy.conf.uif_file) {
2158 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2159 curproxy->conf.uif_line = defproxy.conf.uif_line;
2160 }
William Lallemanda73203e2012-03-12 12:48:57 +01002161
2162 /* copy default header unique id */
2163 if (defproxy.header_unique_id)
2164 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2165
William Lallemand82fe75c2012-10-23 10:25:10 +02002166 /* default compression options */
2167 if (defproxy.comp != NULL) {
2168 curproxy->comp = calloc(1, sizeof(struct comp));
2169 curproxy->comp->algos = defproxy.comp->algos;
2170 curproxy->comp->types = defproxy.comp->types;
2171 }
2172
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002174 curproxy->conf.used_listener_id = EB_ROOT;
2175 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002176
Willy Tarreau93893792009-07-23 13:19:11 +02002177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 }
2179 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2180 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002181 /* FIXME-20070101: we should do this too at the end of the
2182 * config parsing to free all default values.
2183 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002184 free(defproxy.check_req);
2185 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002186 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002187 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002188 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002189 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002190 free(defproxy.capture_name);
2191 free(defproxy.monitor_uri);
2192 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002193 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002194 free(defproxy.fwdfor_hdr_name);
2195 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002196 free(defproxy.orgto_hdr_name);
2197 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002198 free(defproxy.server_id_hdr_name);
2199 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002200 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002201 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002202 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002203 free(defproxy.expect_regex);
2204 defproxy.expect_regex = NULL;
2205 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002206
Willy Tarreau62a61232013-04-12 18:13:46 +02002207 if (defproxy.conf.logformat_string != default_http_log_format &&
2208 defproxy.conf.logformat_string != default_tcp_log_format &&
2209 defproxy.conf.logformat_string != clf_http_log_format)
2210 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002211
Willy Tarreau62a61232013-04-12 18:13:46 +02002212 free(defproxy.conf.uniqueid_format_string);
2213 free(defproxy.conf.lfs_file);
2214 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002215
Willy Tarreaua534fea2008-08-03 12:19:50 +02002216 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002217 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002218
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 /* we cannot free uri_auth because it might already be used */
2220 init_default_instance();
2221 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002222 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2223 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 }
2227 else if (curproxy == NULL) {
2228 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002232
2233 /* update the current file and line being parsed */
2234 curproxy->conf.args.file = curproxy->conf.file;
2235 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002236
2237 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002238 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2239 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2240 if (err_code & ERR_FATAL)
2241 goto out;
2242 }
2243 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002244 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002245 int cur_arg;
2246
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 if (curproxy == &defproxy) {
2248 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002252 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254
Willy Tarreau24709282013-03-10 21:32:12 +01002255 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002256 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002261
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002262 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002263
2264 /* use default settings for unix sockets */
2265 bind_conf->ux.uid = global.unix_bind.ux.uid;
2266 bind_conf->ux.gid = global.unix_bind.ux.gid;
2267 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002268
2269 /* NOTE: the following line might create several listeners if there
2270 * are comma-separated IPs or port ranges. So all further processing
2271 * will have to be applied to all listeners created after last_listen.
2272 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002273 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2274 if (errmsg && *errmsg) {
2275 indent_msg(&errmsg, 2);
2276 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002277 }
2278 else
2279 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2280 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
2283 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002284
Willy Tarreau4348fad2012-09-20 16:48:07 +02002285 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2286 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002287 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002288 }
2289
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002290 cur_arg = 2;
2291 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002292 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002293 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002294 char *err;
2295
Willy Tarreau26982662012-09-12 23:17:10 +02002296 kw = bind_find_kw(args[cur_arg]);
2297 if (kw) {
2298 char *err = NULL;
2299 int code;
2300
2301 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002302 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2303 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002304 cur_arg += 1 + kw->skip ;
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308
Willy Tarreau4348fad2012-09-20 16:48:07 +02002309 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002310 err_code |= code;
2311
2312 if (code) {
2313 if (err && *err) {
2314 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002315 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002316 }
2317 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002318 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2319 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002320 if (code & ERR_FATAL) {
2321 free(err);
2322 cur_arg += 1 + kw->skip;
2323 goto out;
2324 }
2325 }
2326 free(err);
2327 cur_arg += 1 + kw->skip;
2328 continue;
2329 }
2330
Willy Tarreau8638f482012-09-18 18:01:17 +02002331 err = NULL;
2332 if (!bind_dumped) {
2333 bind_dump_kws(&err);
2334 indent_msg(&err, 4);
2335 bind_dumped = 1;
2336 }
2337
2338 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2339 file, linenum, args[0], args[1], args[cur_arg],
2340 err ? " Registered keywords :" : "", err ? err : "");
2341 free(err);
2342
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002345 }
Willy Tarreau93893792009-07-23 13:19:11 +02002346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 }
2348 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002349 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2351 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002355 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 /* flush useless bits */
2359 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002362 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002363 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002364 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002365
Willy Tarreau1c47f852006-07-09 08:22:27 +02002366 if (!*args[1]) {
2367 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2368 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002371 }
2372
Willy Tarreaua534fea2008-08-03 12:19:50 +02002373 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002374 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002375 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002376 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002377 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2378
Willy Tarreau93893792009-07-23 13:19:11 +02002379 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2382 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2383 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2384 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2385 else {
2386 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 }
2390 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002391 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002392 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002393
2394 if (curproxy == &defproxy) {
2395 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2396 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002399 }
2400
2401 if (!*args[1]) {
2402 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002406 }
2407
2408 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002409 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002410
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002411 if (curproxy->uuid <= 0) {
2412 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002413 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002416 }
2417
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002418 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2419 if (node) {
2420 struct proxy *target = container_of(node, struct proxy, conf.id);
2421 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2422 file, linenum, proxy_type_str(curproxy), curproxy->id,
2423 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
2426 }
2427 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002428 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002429 else if (!strcmp(args[0], "description")) {
2430 int i, len=0;
2431 char *d;
2432
Cyril Bonté99ed3272010-01-24 23:29:44 +01002433 if (curproxy == &defproxy) {
2434 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2435 file, linenum, args[0]);
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002440 if (!*args[1]) {
2441 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2442 file, linenum, args[0]);
2443 return -1;
2444 }
2445
Willy Tarreau348acfe2014-04-14 15:00:39 +02002446 for (i = 1; *args[i]; i++)
2447 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002448
2449 d = (char *)calloc(1, len);
2450 curproxy->desc = d;
2451
Willy Tarreau348acfe2014-04-14 15:00:39 +02002452 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2453 for (i = 2; *args[i]; i++)
2454 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002455
2456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2458 curproxy->state = PR_STSTOPPED;
2459 }
2460 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2461 curproxy->state = PR_STNEW;
2462 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002463 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2464 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002465 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002466
2467 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002468 unsigned int low, high;
2469
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002470 if (strcmp(args[cur_arg], "all") == 0) {
2471 set = 0;
2472 break;
2473 }
2474 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002475 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002476 }
2477 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002478 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002479 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002480 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002481 char *dash = strchr(args[cur_arg], '-');
2482
2483 low = high = str2uic(args[cur_arg]);
2484 if (dash)
2485 high = str2uic(dash + 1);
2486
2487 if (high < low) {
2488 unsigned int swap = low;
2489 low = high;
2490 high = swap;
2491 }
2492
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002493 if (low < 1 || high > LONGBITS) {
2494 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2495 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002498 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002499 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002500 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002501 }
2502 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002503 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2504 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002507 }
2508 cur_arg++;
2509 }
2510 curproxy->bind_proc = set;
2511 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002512 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002513 if (curproxy == &defproxy) {
2514 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002517 }
2518
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002519 err = invalid_char(args[1]);
2520 if (err) {
2521 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2522 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002524 }
2525
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002526 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002527 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2528 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002531 }
2532 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2534 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535
Willy Tarreau977b8e42006-12-29 14:19:17 +01002536 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002538
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 if (*(args[1]) == 0) {
2540 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2541 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002545
Willy Tarreau67402132012-05-31 20:40:20 +02002546 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002547 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002548 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002549 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 curproxy->cookie_name = strdup(args[1]);
2551 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002552
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 cur_arg = 2;
2554 while (*(args[cur_arg])) {
2555 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002556 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 }
2558 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002559 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
2561 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002562 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 }
2564 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002565 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 }
2567 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002568 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002570 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002571 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002574 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002576 else if (!strcmp(args[cur_arg], "httponly")) {
2577 curproxy->ck_opts |= PR_CK_HTTPONLY;
2578 }
2579 else if (!strcmp(args[cur_arg], "secure")) {
2580 curproxy->ck_opts |= PR_CK_SECURE;
2581 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002582 else if (!strcmp(args[cur_arg], "domain")) {
2583 if (!*args[cur_arg + 1]) {
2584 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2585 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002588 }
2589
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002590 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002591 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002592 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2593 " dots nor does not start with a dot."
2594 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002595 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002596 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002597 }
2598
2599 err = invalid_domainchar(args[cur_arg + 1]);
2600 if (err) {
2601 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2602 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002605 }
2606
Willy Tarreau68a897b2009-12-03 23:28:34 +01002607 if (!curproxy->cookie_domain) {
2608 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2609 } else {
2610 /* one domain was already specified, add another one by
2611 * building the string which will be returned along with
2612 * the cookie.
2613 */
2614 char *new_ptr;
2615 int new_len = strlen(curproxy->cookie_domain) +
2616 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2617 new_ptr = malloc(new_len);
2618 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2619 free(curproxy->cookie_domain);
2620 curproxy->cookie_domain = new_ptr;
2621 }
Willy Tarreau31936852010-10-06 16:59:56 +02002622 cur_arg++;
2623 }
2624 else if (!strcmp(args[cur_arg], "maxidle")) {
2625 unsigned int maxidle;
2626 const char *res;
2627
2628 if (!*args[cur_arg + 1]) {
2629 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2630 file, linenum, args[cur_arg]);
2631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
2633 }
2634
2635 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2636 if (res) {
2637 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2638 file, linenum, *res, args[cur_arg]);
2639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
2641 }
2642 curproxy->cookie_maxidle = maxidle;
2643 cur_arg++;
2644 }
2645 else if (!strcmp(args[cur_arg], "maxlife")) {
2646 unsigned int maxlife;
2647 const char *res;
2648
2649 if (!*args[cur_arg + 1]) {
2650 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2651 file, linenum, args[cur_arg]);
2652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
2654 }
2655
2656 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2657 if (res) {
2658 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2659 file, linenum, *res, args[cur_arg]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002664 cur_arg++;
2665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002667 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 +02002668 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 }
2672 cur_arg++;
2673 }
Willy Tarreau67402132012-05-31 20:40:20 +02002674 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2676 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 }
2679
Willy Tarreau67402132012-05-31 20:40:20 +02002680 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2682 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002685
Willy Tarreau67402132012-05-31 20:40:20 +02002686 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002687 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2688 file, linenum);
2689 err_code |= ERR_ALERT | ERR_FATAL;
2690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002692 else if (!strcmp(args[0], "persist")) { /* persist */
2693 if (*(args[1]) == 0) {
2694 Alert("parsing [%s:%d] : missing persist method.\n",
2695 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002698 }
2699
2700 if (!strncmp(args[1], "rdp-cookie", 10)) {
2701 curproxy->options2 |= PR_O2_RDPC_PRST;
2702
Emeric Brunb982a3d2010-01-04 15:45:53 +01002703 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002704 const char *beg, *end;
2705
2706 beg = args[1] + 11;
2707 end = strchr(beg, ')');
2708
2709 if (!end || end == beg) {
2710 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2711 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002714 }
2715
2716 free(curproxy->rdp_cookie_name);
2717 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2718 curproxy->rdp_cookie_len = end-beg;
2719 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002720 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002721 free(curproxy->rdp_cookie_name);
2722 curproxy->rdp_cookie_name = strdup("msts");
2723 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2724 }
2725 else { /* syntax */
2726 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2727 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002730 }
2731 }
2732 else {
2733 Alert("parsing [%s:%d] : unknown persist method.\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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002740 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002742 if (curproxy == &defproxy) {
2743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
2746 }
2747
Willy Tarreau977b8e42006-12-29 14:19:17 +01002748 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002750
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002752 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
2757 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002758 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 curproxy->appsession_name = strdup(args[1]);
2760 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2761 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002762 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2763 if (err) {
2764 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2765 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002768 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002769 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002770
Willy Tarreau51041c72007-09-09 21:56:53 +02002771 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2772 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_ABORT;
2774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002776
2777 cur_arg = 6;
2778 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002779 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2780 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002781 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002782 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002783 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002784 } else if (!strcmp(args[cur_arg], "prefix")) {
2785 curproxy->options2 |= PR_O2_AS_PFX;
2786 } else if (!strcmp(args[cur_arg], "mode")) {
2787 if (!*args[cur_arg + 1]) {
2788 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2789 file, linenum, args[0], args[cur_arg]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793
2794 cur_arg++;
2795 if (!strcmp(args[cur_arg], "query-string")) {
2796 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2797 curproxy->options2 |= PR_O2_AS_M_QS;
2798 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2799 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2800 curproxy->options2 |= PR_O2_AS_M_PP;
2801 } else {
2802 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
2805 }
2806 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002807 cur_arg++;
2808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809 } /* Url App Session */
2810 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002811 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002813
Willy Tarreaubaaee002006-06-26 02:48:02 +02002814 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002815 if (curproxy == &defproxy) {
2816 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
2820
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 if (*(args[4]) == 0) {
2822 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2823 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002827 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 curproxy->capture_name = strdup(args[2]);
2829 curproxy->capture_namelen = strlen(curproxy->capture_name);
2830 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 curproxy->to_log |= LW_COOKIE;
2832 }
2833 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2834 struct cap_hdr *hdr;
2835
2836 if (curproxy == &defproxy) {
2837 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 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
2841
2842 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2843 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2844 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 hdr = calloc(sizeof(struct cap_hdr), 1);
2850 hdr->next = curproxy->req_cap;
2851 hdr->name = strdup(args[3]);
2852 hdr->namelen = strlen(args[3]);
2853 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002854 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 hdr->index = curproxy->nb_req_cap++;
2856 curproxy->req_cap = hdr;
2857 curproxy->to_log |= LW_REQHDR;
2858 }
2859 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2860 struct cap_hdr *hdr;
2861
2862 if (curproxy == &defproxy) {
2863 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 +02002864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 }
2867
2868 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2869 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2870 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 hdr = calloc(sizeof(struct cap_hdr), 1);
2875 hdr->next = curproxy->rsp_cap;
2876 hdr->name = strdup(args[3]);
2877 hdr->namelen = strlen(args[3]);
2878 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002879 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 hdr->index = curproxy->nb_rsp_cap++;
2881 curproxy->rsp_cap = hdr;
2882 curproxy->to_log |= LW_RSPHDR;
2883 }
2884 else {
2885 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }
2890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002892 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002894
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 if (*(args[1]) == 0) {
2896 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2897 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 }
2901 curproxy->conn_retries = atol(args[1]);
2902 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002903 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002904 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002905
2906 if (curproxy == &defproxy) {
2907 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2908 err_code |= ERR_ALERT | ERR_FATAL;
2909 goto out;
2910 }
2911
Willy Tarreau20b0de52012-12-24 15:45:22 +01002912 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2913 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2914 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2915 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002916 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002917 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2918 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 +01002919 file, linenum, args[0]);
2920 err_code |= ERR_WARN;
2921 }
2922
Willy Tarreauff011f22011-01-06 17:51:27 +01002923 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002924
Willy Tarreauff011f22011-01-06 17:51:27 +01002925 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002926 err_code |= ERR_ALERT | ERR_ABORT;
2927 goto out;
2928 }
2929
Willy Tarreau5002f572014-04-23 01:32:02 +02002930 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002931 err_code |= warnif_cond_conflicts(rule->cond,
2932 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2933 file, linenum);
2934
Willy Tarreauff011f22011-01-06 17:51:27 +01002935 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002936 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002937 else if (!strcmp(args[0], "http-response")) { /* response access control */
2938 struct http_res_rule *rule;
2939
2940 if (curproxy == &defproxy) {
2941 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
2946 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2947 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2948 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2949 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2950 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2951 file, linenum, args[0]);
2952 err_code |= ERR_WARN;
2953 }
2954
2955 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2956
2957 if (!rule) {
2958 err_code |= ERR_ALERT | ERR_ABORT;
2959 goto out;
2960 }
2961
2962 err_code |= warnif_cond_conflicts(rule->cond,
2963 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2964 file, linenum);
2965
2966 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2967 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002968 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2969 /* set the header name and length into the proxy structure */
2970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2971 err_code |= ERR_WARN;
2972
2973 if (!*args[1]) {
2974 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2975 file, linenum, args[0]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979
2980 /* set the desired header name */
2981 free(curproxy->server_id_hdr_name);
2982 curproxy->server_id_hdr_name = strdup(args[1]);
2983 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2984 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002985 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002986 struct http_req_rule *rule;
2987
Willy Tarreaub099aca2008-10-12 17:26:37 +02002988 if (curproxy == &defproxy) {
2989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002992 }
2993
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002994 /* emulate "block" using "http-request block". Since these rules are supposed to
2995 * be processed before all http-request rules, we put them into their own list
2996 * and will insert them at the end.
2997 */
2998 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2999 if (!rule) {
3000 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003001 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003002 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003003 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3004 err_code |= warnif_cond_conflicts(rule->cond,
3005 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3006 file, linenum);
3007 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003008
3009 if (!already_warned(WARN_BLOCK_DEPRECATED))
3010 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]);
3011
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003012 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003013 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003014 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003015
Cyril Bonté99ed3272010-01-24 23:29:44 +01003016 if (curproxy == &defproxy) {
3017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003022 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003023 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3024 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003027 }
3028
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003029 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003030 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003031 err_code |= warnif_cond_conflicts(rule->cond,
3032 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3033 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003034 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003035 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003036 struct switching_rule *rule;
3037
Willy Tarreaub099aca2008-10-12 17:26:37 +02003038 if (curproxy == &defproxy) {
3039 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003042 }
3043
Willy Tarreau55ea7572007-06-17 19:56:27 +02003044 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003046
3047 if (*(args[1]) == 0) {
3048 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003051 }
3052
Willy Tarreauf51658d2014-04-23 01:21:56 +02003053 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3054 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3055 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3056 file, linenum, errmsg);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003060
Willy Tarreauf51658d2014-04-23 01:21:56 +02003061 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003062 }
3063
3064 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3065 rule->cond = cond;
3066 rule->be.name = strdup(args[1]);
3067 LIST_INIT(&rule->list);
3068 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3069 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003070 else if (strcmp(args[0], "use-server") == 0) {
3071 struct server_rule *rule;
3072
3073 if (curproxy == &defproxy) {
3074 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
3077 }
3078
3079 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3080 err_code |= ERR_WARN;
3081
3082 if (*(args[1]) == 0) {
3083 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
3086 }
3087
3088 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3089 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3090 file, linenum, args[0]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003095 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3096 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3097 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003102 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003103
3104 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3105 rule->cond = cond;
3106 rule->srv.name = strdup(args[1]);
3107 LIST_INIT(&rule->list);
3108 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3109 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3110 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003111 else if ((!strcmp(args[0], "force-persist")) ||
3112 (!strcmp(args[0], "ignore-persist"))) {
3113 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003114
3115 if (curproxy == &defproxy) {
3116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
3121 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3122 err_code |= ERR_WARN;
3123
Willy Tarreauef6494c2010-01-28 17:12:36 +01003124 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003125 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3126 file, linenum, args[0]);
3127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003131 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3132 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3133 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
3136 }
3137
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003138 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3139 * where force-persist is applied.
3140 */
3141 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003142
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003143 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003144 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003145 if (!strcmp(args[0], "force-persist")) {
3146 rule->type = PERSIST_TYPE_FORCE;
3147 } else {
3148 rule->type = PERSIST_TYPE_IGNORE;
3149 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003150 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003151 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003152 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003153 else if (!strcmp(args[0], "stick-table")) {
3154 int myidx = 1;
3155
Emeric Brun32da3c42010-09-23 18:39:19 +02003156 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003157 curproxy->table.type = (unsigned int)-1;
3158 while (*args[myidx]) {
3159 const char *err;
3160
3161 if (strcmp(args[myidx], "size") == 0) {
3162 myidx++;
3163 if (!*(args[myidx])) {
3164 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3165 file, linenum, args[myidx-1]);
3166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
3168 }
3169 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3170 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3171 file, linenum, *err, args[myidx-1]);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003175 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003176 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003177 else if (strcmp(args[myidx], "peers") == 0) {
3178 myidx++;
Godbach50523162013-12-11 19:48:57 +08003179 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003180 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3181 file, linenum, args[myidx-1]);
3182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
Godbach50523162013-12-11 19:48:57 +08003184 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003185 curproxy->table.peers.name = strdup(args[myidx++]);
3186 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003187 else if (strcmp(args[myidx], "expire") == 0) {
3188 myidx++;
3189 if (!*(args[myidx])) {
3190 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3191 file, linenum, args[myidx-1]);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
3195 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3196 if (err) {
3197 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3198 file, linenum, *err, args[myidx-1]);
3199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
3201 }
3202 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003203 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003204 }
3205 else if (strcmp(args[myidx], "nopurge") == 0) {
3206 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003207 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003208 }
3209 else if (strcmp(args[myidx], "type") == 0) {
3210 myidx++;
3211 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3212 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3213 file, linenum, args[myidx]);
3214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
3216 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003217 /* myidx already points to next arg */
3218 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003219 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003220 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003221 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003222
3223 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003224 nw = args[myidx];
3225 while (*nw) {
3226 /* the "store" keyword supports a comma-separated list */
3227 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003228 sa = NULL; /* store arg */
3229 while (*nw && *nw != ',') {
3230 if (*nw == '(') {
3231 *nw = 0;
3232 sa = ++nw;
3233 while (*nw != ')') {
3234 if (!*nw) {
3235 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3236 file, linenum, args[0], cw);
3237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
3239 }
3240 nw++;
3241 }
3242 *nw = '\0';
3243 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003244 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003245 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003246 if (*nw)
3247 *nw++ = '\0';
3248 type = stktable_get_data_type(cw);
3249 if (type < 0) {
3250 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3251 file, linenum, args[0], cw);
3252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
3254 }
Willy Tarreauac782882010-06-20 10:41:54 +02003255
3256 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3257 switch (err) {
3258 case PE_NONE: break;
3259 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003260 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3261 file, linenum, args[0], cw);
3262 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003263 break;
3264
3265 case PE_ARG_MISSING:
3266 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3267 file, linenum, args[0], cw);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270
3271 case PE_ARG_NOT_USED:
3272 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3273 file, linenum, args[0], cw);
3274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
3276
3277 default:
3278 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3279 file, linenum, args[0], cw);
3280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003282 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003283 }
3284 myidx++;
3285 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003286 else {
3287 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3288 file, linenum, args[myidx]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003291 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003292 }
3293
3294 if (!curproxy->table.size) {
3295 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3296 file, linenum);
3297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
3299 }
3300
3301 if (curproxy->table.type == (unsigned int)-1) {
3302 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3303 file, linenum);
3304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
3306 }
3307 }
3308 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003309 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003310 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003311 int myidx = 0;
3312 const char *name = NULL;
3313 int flags;
3314
3315 if (curproxy == &defproxy) {
3316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
3319 }
3320
3321 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3322 err_code |= ERR_WARN;
3323 goto out;
3324 }
3325
3326 myidx++;
3327 if ((strcmp(args[myidx], "store") == 0) ||
3328 (strcmp(args[myidx], "store-request") == 0)) {
3329 myidx++;
3330 flags = STK_IS_STORE;
3331 }
3332 else if (strcmp(args[myidx], "store-response") == 0) {
3333 myidx++;
3334 flags = STK_IS_STORE | STK_ON_RSP;
3335 }
3336 else if (strcmp(args[myidx], "match") == 0) {
3337 myidx++;
3338 flags = STK_IS_MATCH;
3339 }
3340 else if (strcmp(args[myidx], "on") == 0) {
3341 myidx++;
3342 flags = STK_IS_MATCH | STK_IS_STORE;
3343 }
3344 else {
3345 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349
3350 if (*(args[myidx]) == 0) {
3351 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
3354 }
3355
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003356 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003357 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003358 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003359 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363
3364 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003365 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3366 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3367 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003368 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003369 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003370 goto out;
3371 }
3372 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003373 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3374 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3375 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003376 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003377 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003378 goto out;
3379 }
3380 }
3381
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003382 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003383 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003384
Emeric Brunb982a3d2010-01-04 15:45:53 +01003385 if (strcmp(args[myidx], "table") == 0) {
3386 myidx++;
3387 name = args[myidx++];
3388 }
3389
Willy Tarreauef6494c2010-01-28 17:12:36 +01003390 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003391 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3392 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3393 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003394 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003395 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003396 goto out;
3397 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003398 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003399 else if (*(args[myidx])) {
3400 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3401 file, linenum, args[0], args[myidx]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003403 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003404 goto out;
3405 }
Emeric Brun97679e72010-09-23 17:56:44 +02003406 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003407 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003408 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003409 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003410
Emeric Brunb982a3d2010-01-04 15:45:53 +01003411 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3412 rule->cond = cond;
3413 rule->expr = expr;
3414 rule->flags = flags;
3415 rule->table.name = name ? strdup(name) : NULL;
3416 LIST_INIT(&rule->list);
3417 if (flags & STK_ON_RSP)
3418 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3419 else
3420 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 else if (!strcmp(args[0], "stats")) {
3423 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3424 curproxy->uri_auth = NULL; /* we must detach from the default config */
3425
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003426 if (!*args[1]) {
3427 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003428 } else if (!strcmp(args[1], "admin")) {
3429 struct stats_admin_rule *rule;
3430
3431 if (curproxy == &defproxy) {
3432 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
3435 }
3436
3437 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3438 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3439 err_code |= ERR_ALERT | ERR_ABORT;
3440 goto out;
3441 }
3442
3443 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3444 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3445 file, linenum, args[0], args[1]);
3446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
3448 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003449 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3450 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3451 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003452 err_code |= ERR_ALERT | ERR_FATAL;
3453 goto out;
3454 }
3455
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003456 err_code |= warnif_cond_conflicts(cond,
3457 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3458 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003459
3460 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3461 rule->cond = cond;
3462 LIST_INIT(&rule->list);
3463 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003464 } else if (!strcmp(args[1], "uri")) {
3465 if (*(args[2]) == 0) {
3466 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_ALERT | ERR_ABORT;
3472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 }
3474 } else if (!strcmp(args[1], "realm")) {
3475 if (*(args[2]) == 0) {
3476 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3480 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_ABORT;
3482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003484 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003485 unsigned interval;
3486
3487 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3488 if (err) {
3489 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3490 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003493 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3494 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_ABORT;
3496 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003497 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003498 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003499 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003500
3501 if (curproxy == &defproxy) {
3502 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
3506
3507 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3508 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3509 err_code |= ERR_ALERT | ERR_ABORT;
3510 goto out;
3511 }
3512
Willy Tarreauff011f22011-01-06 17:51:27 +01003513 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3514 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003515 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3516 file, linenum, args[0]);
3517 err_code |= ERR_WARN;
3518 }
3519
Willy Tarreauff011f22011-01-06 17:51:27 +01003520 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003521
Willy Tarreauff011f22011-01-06 17:51:27 +01003522 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003523 err_code |= ERR_ALERT | ERR_ABORT;
3524 goto out;
3525 }
3526
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003527 err_code |= warnif_cond_conflicts(rule->cond,
3528 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3529 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003530 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003531
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 } else if (!strcmp(args[1], "auth")) {
3533 if (*(args[2]) == 0) {
3534 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3538 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_ALERT | ERR_ABORT;
3540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 }
3542 } else if (!strcmp(args[1], "scope")) {
3543 if (*(args[2]) == 0) {
3544 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3548 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_ABORT;
3550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 }
3552 } else if (!strcmp(args[1], "enable")) {
3553 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3554 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_ABORT;
3556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003558 } else if (!strcmp(args[1], "hide-version")) {
3559 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3560 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_ABORT;
3562 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003563 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003564 } else if (!strcmp(args[1], "show-legends")) {
3565 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3566 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3567 err_code |= ERR_ALERT | ERR_ABORT;
3568 goto out;
3569 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003570 } else if (!strcmp(args[1], "show-node")) {
3571
3572 if (*args[2]) {
3573 int i;
3574 char c;
3575
3576 for (i=0; args[2][i]; i++) {
3577 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003578 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3579 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003580 break;
3581 }
3582
3583 if (!i || args[2][i]) {
3584 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3585 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3586 file, linenum, args[0], args[1]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590 }
3591
3592 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3593 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3594 err_code |= ERR_ALERT | ERR_ABORT;
3595 goto out;
3596 }
3597 } else if (!strcmp(args[1], "show-desc")) {
3598 char *desc = NULL;
3599
3600 if (*args[2]) {
3601 int i, len=0;
3602 char *d;
3603
Willy Tarreau348acfe2014-04-14 15:00:39 +02003604 for (i = 2; *args[i]; i++)
3605 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003606
3607 desc = d = (char *)calloc(1, len);
3608
Willy Tarreau348acfe2014-04-14 15:00:39 +02003609 d += snprintf(d, desc + len - d, "%s", args[2]);
3610 for (i = 3; *args[i]; i++)
3611 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003612 }
3613
3614 if (!*args[2] && !global.desc)
3615 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3616 file, linenum, args[1]);
3617 else {
3618 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3619 free(desc);
3620 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3621 err_code |= ERR_ALERT | ERR_ABORT;
3622 goto out;
3623 }
3624 free(desc);
3625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003627stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003628 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 +01003629 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
3633 }
3634 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003635 int optnum;
3636
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003637 if (*(args[1]) == '\0') {
3638 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3639 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003643
3644 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3645 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003646 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3647 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3648 file, linenum, cfg_opts[optnum].name);
3649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
3651 }
Willy Tarreau93893792009-07-23 13:19:11 +02003652 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3653 err_code |= ERR_WARN;
3654 goto out;
3655 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003656
Willy Tarreau3842f002009-06-14 11:39:52 +02003657 curproxy->no_options &= ~cfg_opts[optnum].val;
3658 curproxy->options &= ~cfg_opts[optnum].val;
3659
3660 switch (kwm) {
3661 case KWM_STD:
3662 curproxy->options |= cfg_opts[optnum].val;
3663 break;
3664 case KWM_NO:
3665 curproxy->no_options |= cfg_opts[optnum].val;
3666 break;
3667 case KWM_DEF: /* already cleared */
3668 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003669 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003670
Willy Tarreau93893792009-07-23 13:19:11 +02003671 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003672 }
3673 }
3674
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003675 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3676 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003677 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3678 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3679 file, linenum, cfg_opts2[optnum].name);
3680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
3682 }
Willy Tarreau93893792009-07-23 13:19:11 +02003683 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3684 err_code |= ERR_WARN;
3685 goto out;
3686 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003687
Willy Tarreau3842f002009-06-14 11:39:52 +02003688 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3689 curproxy->options2 &= ~cfg_opts2[optnum].val;
3690
3691 switch (kwm) {
3692 case KWM_STD:
3693 curproxy->options2 |= cfg_opts2[optnum].val;
3694 break;
3695 case KWM_NO:
3696 curproxy->no_options2 |= cfg_opts2[optnum].val;
3697 break;
3698 case KWM_DEF: /* already cleared */
3699 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003700 }
Willy Tarreau93893792009-07-23 13:19:11 +02003701 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003702 }
3703 }
3704
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003705 /* HTTP options override each other. They can be cancelled using
3706 * "no option xxx" which only switches to default mode if the mode
3707 * was this one (useful for cancelling options set in defaults
3708 * sections).
3709 */
3710 if (strcmp(args[1], "httpclose") == 0) {
3711 if (kwm == KWM_STD) {
3712 curproxy->options &= ~PR_O_HTTP_MODE;
3713 curproxy->options |= PR_O_HTTP_PCL;
3714 goto out;
3715 }
3716 else if (kwm == KWM_NO) {
3717 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3718 curproxy->options &= ~PR_O_HTTP_MODE;
3719 goto out;
3720 }
3721 }
3722 else if (strcmp(args[1], "forceclose") == 0) {
3723 if (kwm == KWM_STD) {
3724 curproxy->options &= ~PR_O_HTTP_MODE;
3725 curproxy->options |= PR_O_HTTP_FCL;
3726 goto out;
3727 }
3728 else if (kwm == KWM_NO) {
3729 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3730 curproxy->options &= ~PR_O_HTTP_MODE;
3731 goto out;
3732 }
3733 }
3734 else if (strcmp(args[1], "http-server-close") == 0) {
3735 if (kwm == KWM_STD) {
3736 curproxy->options &= ~PR_O_HTTP_MODE;
3737 curproxy->options |= PR_O_HTTP_SCL;
3738 goto out;
3739 }
3740 else if (kwm == KWM_NO) {
3741 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3742 curproxy->options &= ~PR_O_HTTP_MODE;
3743 goto out;
3744 }
3745 }
3746 else if (strcmp(args[1], "http-keep-alive") == 0) {
3747 if (kwm == KWM_STD) {
3748 curproxy->options &= ~PR_O_HTTP_MODE;
3749 curproxy->options |= PR_O_HTTP_KAL;
3750 goto out;
3751 }
3752 else if (kwm == KWM_NO) {
3753 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3754 curproxy->options &= ~PR_O_HTTP_MODE;
3755 goto out;
3756 }
3757 }
3758 else if (strcmp(args[1], "http-tunnel") == 0) {
3759 if (kwm == KWM_STD) {
3760 curproxy->options &= ~PR_O_HTTP_MODE;
3761 curproxy->options |= PR_O_HTTP_TUN;
3762 goto out;
3763 }
3764 else if (kwm == KWM_NO) {
3765 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3766 curproxy->options &= ~PR_O_HTTP_MODE;
3767 goto out;
3768 }
3769 }
3770
Willy Tarreau3842f002009-06-14 11:39:52 +02003771 if (kwm != KWM_STD) {
3772 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003773 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003776 }
3777
Emeric Brun3a058f32009-06-30 18:26:00 +02003778 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003779 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003781 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003782 if (*(args[2]) != '\0') {
3783 if (!strcmp(args[2], "clf")) {
3784 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003785 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003786 } else {
3787 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003790 }
3791 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003792 if (curproxy->conf.logformat_string != default_http_log_format &&
3793 curproxy->conf.logformat_string != default_tcp_log_format &&
3794 curproxy->conf.logformat_string != clf_http_log_format)
3795 free(curproxy->conf.logformat_string);
3796 curproxy->conf.logformat_string = logformat;
3797
3798 free(curproxy->conf.lfs_file);
3799 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3800 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003801 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003802 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003804 if (curproxy->conf.logformat_string != default_http_log_format &&
3805 curproxy->conf.logformat_string != default_tcp_log_format &&
3806 curproxy->conf.logformat_string != clf_http_log_format)
3807 free(curproxy->conf.logformat_string);
3808 curproxy->conf.logformat_string = default_tcp_log_format;
3809
3810 free(curproxy->conf.lfs_file);
3811 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3812 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 else if (!strcmp(args[1], "tcpka")) {
3815 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003816 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003818
3819 if (curproxy->cap & PR_CAP_FE)
3820 curproxy->options |= PR_O_TCP_CLI_KA;
3821 if (curproxy->cap & PR_CAP_BE)
3822 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
3824 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003825 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_WARN;
3827
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003829 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003830 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003831 curproxy->options2 &= ~PR_O2_CHK_ANY;
3832 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 if (!*args[2]) { /* no argument */
3834 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3835 curproxy->check_len = strlen(DEF_CHECK_REQ);
3836 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003837 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 curproxy->check_req = (char *)malloc(reqlen);
3839 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003840 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003842 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 if (*args[4])
3844 reqlen += strlen(args[4]);
3845 else
3846 reqlen += strlen("HTTP/1.0");
3847
3848 curproxy->check_req = (char *)malloc(reqlen);
3849 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003850 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003852 }
3853 else if (!strcmp(args[1], "ssl-hello-chk")) {
3854 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003857
Willy Tarreaua534fea2008-08-03 12:19:50 +02003858 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003859 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003860 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003861 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 }
Willy Tarreau23677902007-05-08 23:50:35 +02003863 else if (!strcmp(args[1], "smtpchk")) {
3864 /* use SMTP request to check servers' health */
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;
3868 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003869
3870 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3871 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3872 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3873 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3874 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3875 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3876 curproxy->check_req = (char *)malloc(reqlen);
3877 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3878 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3879 } else {
3880 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3881 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3882 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3883 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3884 }
3885 }
3886 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003887 else if (!strcmp(args[1], "pgsql-check")) {
3888 /* use PostgreSQL request to check servers' health */
3889 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3890 err_code |= ERR_WARN;
3891
3892 free(curproxy->check_req);
3893 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003894 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003895 curproxy->options2 |= PR_O2_PGSQL_CHK;
3896
3897 if (*(args[2])) {
3898 int cur_arg = 2;
3899
3900 while (*(args[cur_arg])) {
3901 if (strcmp(args[cur_arg], "user") == 0) {
3902 char * packet;
3903 uint32_t packet_len;
3904 uint32_t pv;
3905
3906 /* suboption header - needs additional argument for it */
3907 if (*(args[cur_arg+1]) == 0) {
3908 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3909 file, linenum, args[0], args[1], args[cur_arg]);
3910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
3912 }
3913
3914 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3915 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3916 pv = htonl(0x30000); /* protocol version 3.0 */
3917
3918 packet = (char*) calloc(1, packet_len);
3919
3920 memcpy(packet + 4, &pv, 4);
3921
3922 /* copy "user" */
3923 memcpy(packet + 8, "user", 4);
3924
3925 /* copy username */
3926 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3927
3928 free(curproxy->check_req);
3929 curproxy->check_req = packet;
3930 curproxy->check_len = packet_len;
3931
3932 packet_len = htonl(packet_len);
3933 memcpy(packet, &packet_len, 4);
3934 cur_arg += 2;
3935 } else {
3936 /* unknown suboption - catchall */
3937 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3938 file, linenum, args[0], args[1]);
3939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
3941 }
3942 } /* end while loop */
3943 }
3944 }
3945
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003946 else if (!strcmp(args[1], "redis-check")) {
3947 /* use REDIS PING request to check servers' health */
3948 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3949 err_code |= ERR_WARN;
3950
3951 free(curproxy->check_req);
3952 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003953 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003954 curproxy->options2 |= PR_O2_REDIS_CHK;
3955
3956 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3957 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3958 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3959 }
3960
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003961 else if (!strcmp(args[1], "mysql-check")) {
3962 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003963 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3964 err_code |= ERR_WARN;
3965
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003966 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003967 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003968 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003969 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003970
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003971 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003972 * const char mysql40_client_auth_pkt[] = {
3973 * "\x0e\x00\x00" // packet length
3974 * "\x01" // packet number
3975 * "\x00\x00" // client capabilities
3976 * "\x00\x00\x01" // max packet
3977 * "haproxy\x00" // username (null terminated string)
3978 * "\x00" // filler (always 0x00)
3979 * "\x01\x00\x00" // packet length
3980 * "\x00" // packet number
3981 * "\x01" // COM_QUIT command
3982 * };
3983 */
3984
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003985 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3986 * const char mysql41_client_auth_pkt[] = {
3987 * "\x0e\x00\x00\" // packet length
3988 * "\x01" // packet number
3989 * "\x00\x00\x00\x00" // client capabilities
3990 * "\x00\x00\x00\x01" // max packet
3991 * "\x21" // character set (UTF-8)
3992 * char[23] // All zeroes
3993 * "haproxy\x00" // username (null terminated string)
3994 * "\x00" // filler (always 0x00)
3995 * "\x01\x00\x00" // packet length
3996 * "\x00" // packet number
3997 * "\x01" // COM_QUIT command
3998 * };
3999 */
4000
4001
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004002 if (*(args[2])) {
4003 int cur_arg = 2;
4004
4005 while (*(args[cur_arg])) {
4006 if (strcmp(args[cur_arg], "user") == 0) {
4007 char *mysqluser;
4008 int packetlen, reqlen, userlen;
4009
4010 /* suboption header - needs additional argument for it */
4011 if (*(args[cur_arg+1]) == 0) {
4012 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4013 file, linenum, args[0], args[1], args[cur_arg]);
4014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016 }
4017 mysqluser = args[cur_arg + 1];
4018 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004019
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004020 if (*(args[cur_arg+2])) {
4021 if (!strcmp(args[cur_arg+2], "post-41")) {
4022 packetlen = userlen + 7 + 27;
4023 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004024
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004025 free(curproxy->check_req);
4026 curproxy->check_req = (char *)calloc(1, reqlen);
4027 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004028
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004029 snprintf(curproxy->check_req, 4, "%c%c%c",
4030 ((unsigned char) packetlen & 0xff),
4031 ((unsigned char) (packetlen >> 8) & 0xff),
4032 ((unsigned char) (packetlen >> 16) & 0xff));
4033
4034 curproxy->check_req[3] = 1;
4035 curproxy->check_req[5] = 130;
4036 curproxy->check_req[11] = 1;
4037 curproxy->check_req[12] = 33;
4038 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4039 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4040 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4041 cur_arg += 3;
4042 } else {
4043 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047 } else {
4048 packetlen = userlen + 7;
4049 reqlen = packetlen + 9;
4050
4051 free(curproxy->check_req);
4052 curproxy->check_req = (char *)calloc(1, reqlen);
4053 curproxy->check_len = reqlen;
4054
4055 snprintf(curproxy->check_req, 4, "%c%c%c",
4056 ((unsigned char) packetlen & 0xff),
4057 ((unsigned char) (packetlen >> 8) & 0xff),
4058 ((unsigned char) (packetlen >> 16) & 0xff));
4059
4060 curproxy->check_req[3] = 1;
4061 curproxy->check_req[5] = 128;
4062 curproxy->check_req[8] = 1;
4063 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4064 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4065 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4066 cur_arg += 2;
4067 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004068 } else {
4069 /* unknown suboption - catchall */
4070 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4071 file, linenum, args[0], args[1]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075 } /* end while loop */
4076 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004077 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004078 else if (!strcmp(args[1], "ldap-check")) {
4079 /* use LDAP request to check servers' health */
4080 free(curproxy->check_req);
4081 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004082 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004083 curproxy->options2 |= PR_O2_LDAP_CHK;
4084
4085 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4086 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4087 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4088 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004089 else if (!strcmp(args[1], "tcp-check")) {
4090 /* use raw TCPCHK send/expect to check servers' health */
4091 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4092 err_code |= ERR_WARN;
4093
4094 free(curproxy->check_req);
4095 curproxy->check_req = NULL;
4096 curproxy->options2 &= ~PR_O2_CHK_ANY;
4097 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4098 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004099 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004100 int cur_arg;
4101
4102 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4103 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004104 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004105
Willy Tarreau87cf5142011-08-19 22:57:24 +02004106 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004107
4108 free(curproxy->fwdfor_hdr_name);
4109 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4110 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4111
4112 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4113 cur_arg = 2;
4114 while (*(args[cur_arg])) {
4115 if (!strcmp(args[cur_arg], "except")) {
4116 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004117 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004118 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4119 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004122 }
4123 /* flush useless bits */
4124 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004125 cur_arg += 2;
4126 } else if (!strcmp(args[cur_arg], "header")) {
4127 /* suboption header - needs additional argument for it */
4128 if (*(args[cur_arg+1]) == 0) {
4129 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4130 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004133 }
4134 free(curproxy->fwdfor_hdr_name);
4135 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4136 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4137 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004138 } else if (!strcmp(args[cur_arg], "if-none")) {
4139 curproxy->options &= ~PR_O_FF_ALWAYS;
4140 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004141 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004142 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004143 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004144 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004147 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004148 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004149 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004150 else if (!strcmp(args[1], "originalto")) {
4151 int cur_arg;
4152
4153 /* insert x-original-to field, but not for the IP address listed as an except.
4154 * set default options (ie: bitfield, header name, etc)
4155 */
4156
4157 curproxy->options |= PR_O_ORGTO;
4158
4159 free(curproxy->orgto_hdr_name);
4160 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4161 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4162
Willy Tarreau87cf5142011-08-19 22:57:24 +02004163 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004164 cur_arg = 2;
4165 while (*(args[cur_arg])) {
4166 if (!strcmp(args[cur_arg], "except")) {
4167 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004168 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 +02004169 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4170 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004173 }
4174 /* flush useless bits */
4175 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4176 cur_arg += 2;
4177 } else if (!strcmp(args[cur_arg], "header")) {
4178 /* suboption header - needs additional argument for it */
4179 if (*(args[cur_arg+1]) == 0) {
4180 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4181 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004184 }
4185 free(curproxy->orgto_hdr_name);
4186 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4187 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4188 cur_arg += 2;
4189 } else {
4190 /* unknown suboption - catchall */
4191 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4192 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004195 }
4196 } /* end while loop */
4197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 else {
4199 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 }
Willy Tarreau93893792009-07-23 13:19:11 +02004203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004205 else if (!strcmp(args[0], "default_backend")) {
4206 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004208
4209 if (*(args[1]) == 0) {
4210 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004213 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004214 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004215 curproxy->defbe.name = strdup(args[1]);
4216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004217 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004218 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004220
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004221 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4222 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 +01004223 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 /* enable reconnections to dispatch */
4226 curproxy->options |= PR_O_REDISP;
4227 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004228 else if (!strcmp(args[0], "http-check")) {
4229 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004230 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004231
4232 if (strcmp(args[1], "disable-on-404") == 0) {
4233 /* enable a graceful server shutdown on an HTTP 404 response */
4234 curproxy->options |= PR_O_DISABLE404;
4235 }
Willy Tarreauef781042010-01-27 11:53:01 +01004236 else if (strcmp(args[1], "send-state") == 0) {
4237 /* enable emission of the apparent state of a server in HTTP checks */
4238 curproxy->options2 |= PR_O2_CHK_SNDST;
4239 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004240 else if (strcmp(args[1], "expect") == 0) {
4241 const char *ptr_arg;
4242 int cur_arg;
4243
4244 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4245 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249
4250 cur_arg = 2;
4251 /* consider exclamation marks, sole or at the beginning of a word */
4252 while (*(ptr_arg = args[cur_arg])) {
4253 while (*ptr_arg == '!') {
4254 curproxy->options2 ^= PR_O2_EXP_INV;
4255 ptr_arg++;
4256 }
4257 if (*ptr_arg)
4258 break;
4259 cur_arg++;
4260 }
4261 /* now ptr_arg points to the beginning of a word past any possible
4262 * exclamation mark, and cur_arg is the argument which holds this word.
4263 */
4264 if (strcmp(ptr_arg, "status") == 0) {
4265 if (!*(args[cur_arg + 1])) {
4266 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4267 file, linenum, args[0], args[1], ptr_arg);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004272 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004273 curproxy->expect_str = strdup(args[cur_arg + 1]);
4274 }
4275 else if (strcmp(ptr_arg, "string") == 0) {
4276 if (!*(args[cur_arg + 1])) {
4277 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4278 file, linenum, args[0], args[1], ptr_arg);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
4282 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004283 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004284 curproxy->expect_str = strdup(args[cur_arg + 1]);
4285 }
4286 else if (strcmp(ptr_arg, "rstatus") == 0) {
4287 if (!*(args[cur_arg + 1])) {
4288 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4289 file, linenum, args[0], args[1], ptr_arg);
4290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
4292 }
4293 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004294 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004295 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004296 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004297 free(curproxy->expect_regex);
4298 curproxy->expect_regex = NULL;
4299 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004300 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004301 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4302 error = NULL;
4303 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4304 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4305 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4306 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
4309 }
4310 }
4311 else if (strcmp(ptr_arg, "rstring") == 0) {
4312 if (!*(args[cur_arg + 1])) {
4313 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4314 file, linenum, args[0], args[1], ptr_arg);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004319 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004320 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004321 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004322 free(curproxy->expect_regex);
4323 curproxy->expect_regex = NULL;
4324 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004325 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004326 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4327 error = NULL;
4328 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4329 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4330 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4331 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 }
4336 else {
4337 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4338 file, linenum, args[0], args[1], ptr_arg);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
4342 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004343 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004344 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 +02004345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004347 }
4348 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004349 else if (!strcmp(args[0], "tcp-check")) {
4350 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4351 err_code |= ERR_WARN;
4352
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004353 if (strcmp(args[1], "connect") == 0) {
4354 const char *ptr_arg;
4355 int cur_arg;
4356 struct tcpcheck_rule *tcpcheck;
4357 struct list *l;
4358
4359 /* check if first rule is also a 'connect' action */
4360 l = (struct list *)&curproxy->tcpcheck_rules;
4361 if (l->p != l->n) {
4362 tcpcheck = (struct tcpcheck_rule *)l->n;
4363 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4364 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4365 file, linenum);
4366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
4368 }
4369 }
4370
4371 cur_arg = 2;
4372 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4373 tcpcheck->action = TCPCHK_ACT_CONNECT;
4374
4375 /* parsing each parameters to fill up the rule */
4376 while (*(ptr_arg = args[cur_arg])) {
4377 /* tcp port */
4378 if (strcmp(args[cur_arg], "port") == 0) {
4379 if ( (atol(args[cur_arg + 1]) > 65535) ||
4380 (atol(args[cur_arg + 1]) < 1) ){
4381 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4382 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 }
4386 tcpcheck->port = atol(args[cur_arg + 1]);
4387 cur_arg += 2;
4388 }
4389 /* send proxy protocol */
4390 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4391 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4392 cur_arg++;
4393 }
4394#ifdef USE_OPENSSL
4395 else if (strcmp(args[cur_arg], "ssl") == 0) {
4396 curproxy->options |= PR_O_TCPCHK_SSL;
4397 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4398 cur_arg++;
4399 }
4400#endif /* USE_OPENSSL */
4401 else {
4402#ifdef USE_OPENSSL
4403 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4404#else /* USE_OPENSSL */
4405 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4406#endif /* USE_OPENSSL */
4407 file, linenum, args[0], args[1], args[cur_arg]);
4408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
4410 }
4411
4412 }
4413
4414 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4415 }
4416 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004417 if (! *(args[2]) ) {
4418 /* SEND string expected */
4419 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4420 file, linenum, args[0], args[1], args[2]);
4421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
4423 } else {
4424 struct tcpcheck_rule *tcpcheck;
4425
4426 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4427
4428 tcpcheck->action = TCPCHK_ACT_SEND;
4429 tcpcheck->string_len = strlen(args[2]);
4430 tcpcheck->string = strdup(args[2]);
4431 tcpcheck->expect_regex = NULL;
4432
4433 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4434 }
4435 }
4436 else if (strcmp(args[1], "send-binary") == 0) {
4437 if (! *(args[2]) ) {
4438 /* SEND binary string expected */
4439 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4440 file, linenum, args[0], args[1], args[2]);
4441 err_code |= ERR_ALERT | ERR_FATAL;
4442 goto out;
4443 } else {
4444 struct tcpcheck_rule *tcpcheck;
4445 char *err = NULL;
4446
4447 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4448
4449 tcpcheck->action = TCPCHK_ACT_SEND;
4450 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4451 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4452 file, linenum, args[0], args[1], args[2], err);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456 tcpcheck->expect_regex = NULL;
4457
4458 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4459 }
4460 }
4461 else if (strcmp(args[1], "expect") == 0) {
4462 const char *ptr_arg;
4463 int cur_arg;
4464 int inverse = 0;
4465
4466 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4467 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
4470 }
4471
4472 cur_arg = 2;
4473 /* consider exclamation marks, sole or at the beginning of a word */
4474 while (*(ptr_arg = args[cur_arg])) {
4475 while (*ptr_arg == '!') {
4476 inverse = !inverse;
4477 ptr_arg++;
4478 }
4479 if (*ptr_arg)
4480 break;
4481 cur_arg++;
4482 }
4483 /* now ptr_arg points to the beginning of a word past any possible
4484 * exclamation mark, and cur_arg is the argument which holds this word.
4485 */
4486 if (strcmp(ptr_arg, "binary") == 0) {
4487 if (!*(args[cur_arg + 1])) {
4488 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4489 file, linenum, args[0], args[1], ptr_arg);
4490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
4492 }
4493 struct tcpcheck_rule *tcpcheck;
4494 char *err = NULL;
4495
4496 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4497
4498 tcpcheck->action = TCPCHK_ACT_EXPECT;
4499 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4500 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4501 file, linenum, args[0], args[1], args[2], err);
4502 err_code |= ERR_ALERT | ERR_FATAL;
4503 goto out;
4504 }
4505 tcpcheck->expect_regex = NULL;
4506 tcpcheck->inverse = inverse;
4507
4508 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4509 }
4510 else if (strcmp(ptr_arg, "string") == 0) {
4511 if (!*(args[cur_arg + 1])) {
4512 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4513 file, linenum, args[0], args[1], ptr_arg);
4514 err_code |= ERR_ALERT | ERR_FATAL;
4515 goto out;
4516 }
4517 struct tcpcheck_rule *tcpcheck;
4518
4519 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4520
4521 tcpcheck->action = TCPCHK_ACT_EXPECT;
4522 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4523 tcpcheck->string = strdup(args[cur_arg + 1]);
4524 tcpcheck->expect_regex = NULL;
4525 tcpcheck->inverse = inverse;
4526
4527 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4528 }
4529 else if (strcmp(ptr_arg, "rstring") == 0) {
4530 if (!*(args[cur_arg + 1])) {
4531 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4532 file, linenum, args[0], args[1], ptr_arg);
4533 err_code |= ERR_ALERT | ERR_FATAL;
4534 goto out;
4535 }
4536 struct tcpcheck_rule *tcpcheck;
4537
4538 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4539
4540 tcpcheck->action = TCPCHK_ACT_EXPECT;
4541 tcpcheck->string_len = 0;
4542 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004543 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4544 error = NULL;
4545 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4546 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4547 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4548 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004549 err_code |= ERR_ALERT | ERR_FATAL;
4550 goto out;
4551 }
4552 tcpcheck->inverse = inverse;
4553
4554 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4555 }
4556 else {
4557 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4558 file, linenum, args[0], args[1], ptr_arg);
4559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
4561 }
4562 }
4563 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004564 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
4568 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004569 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004570 if (curproxy == &defproxy) {
4571 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004574 }
4575
Willy Tarreaub80c2302007-11-30 20:51:32 +01004576 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004578
4579 if (strcmp(args[1], "fail") == 0) {
4580 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004581 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004582 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4583 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004586 }
4587
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004588 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4589 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4590 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004593 }
4594 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4595 }
4596 else {
4597 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 Tarreaubaaee002006-06-26 02:48:02 +02004602#ifdef TPROXY
4603 else if (!strcmp(args[0], "transparent")) {
4604 /* enable transparent proxy connections */
4605 curproxy->options |= PR_O_TRANSP;
4606 }
4607#endif
4608 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004609 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004611
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 if (*(args[1]) == 0) {
4613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 }
4617 curproxy->maxconn = atol(args[1]);
4618 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004619 else if (!strcmp(args[0], "backlog")) { /* backlog */
4620 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004622
4623 if (*(args[1]) == 0) {
4624 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004627 }
4628 curproxy->backlog = atol(args[1]);
4629 }
Willy Tarreau86034312006-12-29 00:10:33 +01004630 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004633
Willy Tarreau86034312006-12-29 00:10:33 +01004634 if (*(args[1]) == 0) {
4635 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004638 }
4639 curproxy->fullconn = atol(args[1]);
4640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4642 if (*(args[1]) == 0) {
4643 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004647 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4648 if (err) {
4649 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4650 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004653 }
4654 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 }
4656 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004657 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004658 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004659 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004660
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 if (curproxy == &defproxy) {
4662 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004666 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004668
Willy Tarreau902636f2013-03-10 19:44:48 +01004669 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004670 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004671 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004672 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004673 goto out;
4674 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004675
4676 proto = protocol_by_family(sk->ss_family);
4677 if (!proto || !proto->connect) {
4678 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4679 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
4683
4684 if (port1 != port2) {
4685 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4686 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004687 err_code |= ERR_ALERT | ERR_FATAL;
4688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004690
4691 if (!port1) {
4692 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4693 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004697
Willy Tarreaud5191e72010-02-09 20:50:45 +01004698 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004699 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 }
4701 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004702 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004703 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004704
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004705 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4706 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004711 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004712 /**
4713 * The syntax for hash-type config element is
4714 * hash-type {map-based|consistent} [[<algo>] avalanche]
4715 *
4716 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4717 */
4718 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004719
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4721 err_code |= ERR_WARN;
4722
4723 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004724 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4725 }
4726 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004727 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4728 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004729 else if (strcmp(args[1], "avalanche") == 0) {
4730 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]);
4731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004733 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004734 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004735 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004736 err_code |= ERR_ALERT | ERR_FATAL;
4737 goto out;
4738 }
Bhaskar98634f02013-10-29 23:30:51 -04004739
4740 /* set the hash function to use */
4741 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004742 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004743 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004744
4745 /* if consistent with no argument, then avalanche modifier is also applied */
4746 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4747 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004748 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004749 /* set the hash function */
4750 if (!strcmp(args[2], "sdbm")) {
4751 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4752 }
4753 else if (!strcmp(args[2], "djb2")) {
4754 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004755 } else if (!strcmp(args[2], "wt6")) {
4756 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004757 }
4758 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004759 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 -05004760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
4762 }
4763
4764 /* set the hash modifier */
4765 if (!strcmp(args[3], "avalanche")) {
4766 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4767 }
4768 else if (*args[3]) {
4769 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004773 }
William Lallemanda73203e2012-03-12 12:48:57 +01004774 }
William Lallemanda73203e2012-03-12 12:48:57 +01004775 else if (strcmp(args[0], "unique-id-format") == 0) {
4776 if (!*(args[1])) {
4777 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
William Lallemand3203ff42012-11-11 17:30:56 +01004781 if (*(args[2])) {
4782 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
4785 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004786 free(curproxy->conf.uniqueid_format_string);
4787 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004788
Willy Tarreau62a61232013-04-12 18:13:46 +02004789 free(curproxy->conf.uif_file);
4790 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4791 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004792 }
William Lallemanda73203e2012-03-12 12:48:57 +01004793
4794 else if (strcmp(args[0], "unique-id-header") == 0) {
4795 if (!*(args[1])) {
4796 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
4800 free(curproxy->header_unique_id);
4801 curproxy->header_unique_id = strdup(args[1]);
4802 }
4803
William Lallemand723b73a2012-02-08 16:37:49 +01004804 else if (strcmp(args[0], "log-format") == 0) {
4805 if (!*(args[1])) {
4806 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 }
William Lallemand3203ff42012-11-11 17:30:56 +01004810 if (*(args[2])) {
4811 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
4814 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004815
Willy Tarreau62a61232013-04-12 18:13:46 +02004816 if (curproxy->conf.logformat_string != default_http_log_format &&
4817 curproxy->conf.logformat_string != default_tcp_log_format &&
4818 curproxy->conf.logformat_string != clf_http_log_format)
4819 free(curproxy->conf.logformat_string);
4820 curproxy->conf.logformat_string = strdup(args[1]);
4821
4822 free(curproxy->conf.lfs_file);
4823 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4824 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004825
4826 /* get a chance to improve log-format error reporting by
4827 * reporting the correct line-number when possible.
4828 */
4829 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4830 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4831 file, linenum, curproxy->id);
4832 err_code |= ERR_WARN;
4833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 }
William Lallemand723b73a2012-02-08 16:37:49 +01004835
William Lallemand0f99e342011-10-12 17:50:54 +02004836 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4837 /* delete previous herited or defined syslog servers */
4838 struct logsrv *back;
4839
4840 if (*(args[1]) != 0) {
4841 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
4844 }
4845
William Lallemand723b73a2012-02-08 16:37:49 +01004846 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4847 LIST_DEL(&tmplogsrv->list);
4848 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004849 }
4850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004852 struct logsrv *logsrv;
4853
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004855 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004856 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004857 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004858 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004859 LIST_INIT(&node->list);
4860 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
4863 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004864 struct sockaddr_storage *sk;
4865 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004866 int arg = 0;
4867 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004868
4869 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004871 /* just after the address, a length may be specified */
4872 if (strcmp(args[arg+2], "len") == 0) {
4873 len = atoi(args[arg+3]);
4874 if (len < 80 || len > 65535) {
4875 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4876 file, linenum, args[arg+3]);
4877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
4880 logsrv->maxlen = len;
4881
4882 /* skip these two args */
4883 arg += 2;
4884 }
4885 else
4886 logsrv->maxlen = MAX_SYSLOG_LEN;
4887
4888 if (logsrv->maxlen > global.max_syslog_len) {
4889 global.max_syslog_len = logsrv->maxlen;
4890 logline = realloc(logline, global.max_syslog_len + 1);
4891 }
4892
4893 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004894 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004895 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
4898
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 }
4900
William Lallemand0f99e342011-10-12 17:50:54 +02004901 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004902 if (*(args[arg+3])) {
4903 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004904 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004905 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004906 err_code |= ERR_ALERT | ERR_FATAL;
4907 goto out;
4908
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 }
4910 }
4911
William Lallemand0f99e342011-10-12 17:50:54 +02004912 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004913 if (*(args[arg+4])) {
4914 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004915 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004916 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
4919
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004920 }
4921 }
4922
Willy Tarreau902636f2013-03-10 19:44:48 +01004923 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004924 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004925 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004926 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004927 goto out;
4928 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004929
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004930 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004931
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004932 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004933 if (port1 != port2) {
4934 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4935 file, linenum, args[0], args[1]);
4936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
4938 }
4939
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004940 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004941 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
William Lallemand0f99e342011-10-12 17:50:54 +02004943
4944 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
4946 else {
4947 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4948 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 }
4953 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004954 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004955 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004956 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004957 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004958
Willy Tarreau977b8e42006-12-29 14:19:17 +01004959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004961
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004963 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4964 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004968
4969 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004970 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4971 free(curproxy->conn_src.iface_name);
4972 curproxy->conn_src.iface_name = NULL;
4973 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004974
Willy Tarreau902636f2013-03-10 19:44:48 +01004975 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004976 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004977 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004978 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004979 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004980 goto out;
4981 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004982
4983 proto = protocol_by_family(sk->ss_family);
4984 if (!proto || !proto->connect) {
4985 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004986 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
4989 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004990
4991 if (port1 != port2) {
4992 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4993 file, linenum, args[0], args[1]);
4994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
4997
Willy Tarreauef9a3602012-12-08 22:29:20 +01004998 curproxy->conn_src.source_addr = *sk;
4999 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005000
5001 cur_arg = 2;
5002 while (*(args[cur_arg])) {
5003 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005004#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5005#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005006 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005007 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5008 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005011 }
5012#endif
5013 if (!*args[cur_arg + 1]) {
5014 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5015 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005018 }
5019
5020 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005021 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5022 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005023 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005024 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5025 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005026 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5027 char *name, *end;
5028
5029 name = args[cur_arg+1] + 7;
5030 while (isspace(*name))
5031 name++;
5032
5033 end = name;
5034 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5035 end++;
5036
Willy Tarreauef9a3602012-12-08 22:29:20 +01005037 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5038 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5039 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5040 curproxy->conn_src.bind_hdr_len = end - name;
5041 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5042 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5043 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005044
5045 /* now look for an occurrence number */
5046 while (isspace(*end))
5047 end++;
5048 if (*end == ',') {
5049 end++;
5050 name = end;
5051 if (*end == '-')
5052 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005053 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005054 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005055 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005056 }
5057
Willy Tarreauef9a3602012-12-08 22:29:20 +01005058 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005059 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5060 " occurrences values smaller than %d.\n",
5061 file, linenum, MAX_HDR_HISTORY);
5062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
5064 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005065 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005066 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005067
Willy Tarreau902636f2013-03-10 19:44:48 +01005068 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005069 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005070 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005071 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005073 goto out;
5074 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005075
5076 proto = protocol_by_family(sk->ss_family);
5077 if (!proto || !proto->connect) {
5078 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5079 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
5082 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005083
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005084 if (port1 != port2) {
5085 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5086 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
5089 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005090 curproxy->conn_src.tproxy_addr = *sk;
5091 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005092 }
5093 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005094#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005095 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005096#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005097#else /* no TPROXY support */
5098 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005099 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005102#endif
5103 cur_arg += 2;
5104 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005105 }
5106
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005107 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5108#ifdef SO_BINDTODEVICE
5109 if (!*args[cur_arg + 1]) {
5110 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005114 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005115 free(curproxy->conn_src.iface_name);
5116 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5117 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 global.last_checks |= LSTCHK_NETADM;
5119#else
5120 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5121 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005124#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005125 cur_arg += 2;
5126 continue;
5127 }
5128 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005129 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005134 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5135 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5136 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005139 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5143 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147
5148 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005149 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005150 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
5154 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005156 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005157 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
5161 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005163 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005164 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
5168 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 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], "reqallow")) { /* allow 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005182 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005184 SMP_OPT_DIR_REQ, ACT_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005188 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005189 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005192 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005194 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005195
5196 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5197 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 +01005198 }
5199 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005201 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005202 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005204 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005205
5206 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5207 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 +01005208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5212 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216
5217 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005218 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005219 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
5223 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005225 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005226 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
5230 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005232 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005233 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 }
5237 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, 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], "reqiallow")) { /* allow 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005251 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005253 SMP_OPT_DIR_REQ, ACT_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005259 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005260
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 if (curproxy == &defproxy) {
5262 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005266 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 if (*(args[1]) == 0) {
5270 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005274
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005275 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005276 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5277 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5278 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
5281 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005282 err_code |= warnif_cond_conflicts(cond,
5283 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5284 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005285 }
5286 else if (*args[2]) {
5287 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5288 file, linenum, args[0], args[2]);
5289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
5291 }
5292
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005293 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005294 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005295 wl->s = strdup(args[1]);
5296 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005297 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
5299 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5302 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005306
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005308 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005309 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005310 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005315 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005316 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 }
5320 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005322 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005323 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005324 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
5327 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005331 err_code |= ERR_ALERT | ERR_FATAL;
5332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 }
5334
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_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005337 args[0], args[1], args[2], (const char **)args+3);
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], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005343 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005344 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005345 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
5348 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005349 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005350 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005351 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005352 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005354 }
5355 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005356 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005357
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 if (curproxy == &defproxy) {
5359 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005360 err_code |= ERR_ALERT | ERR_FATAL;
5361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005363 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005364 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 if (*(args[1]) == 0) {
5367 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 }
5371
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005372 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005373 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5374 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5375 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
5378 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005379 err_code |= warnif_cond_conflicts(cond,
5380 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5381 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005382 }
5383 else if (*args[2]) {
5384 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5385 file, linenum, args[0], args[2]);
5386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
5388 }
5389
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005390 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005391 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005392 wl->s = strdup(args[1]);
5393 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 }
5395 else if (!strcmp(args[0], "errorloc") ||
5396 !strcmp(args[0], "errorloc302") ||
5397 !strcmp(args[0], "errorloc303")) { /* error location */
5398 int errnum, errlen;
5399 char *err;
5400
Willy Tarreau977b8e42006-12-29 14:19:17 +01005401 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005402 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005403
Willy Tarreaubaaee002006-06-26 02:48:02 +02005404 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005405 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408 }
5409
5410 errnum = atol(args[1]);
5411 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005412 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5413 err = malloc(errlen);
5414 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005416 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5417 err = malloc(errlen);
5418 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
5420
Willy Tarreau0f772532006-12-23 20:51:41 +01005421 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5422 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005423 chunk_destroy(&curproxy->errmsg[rc]);
5424 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005425 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005428
5429 if (rc >= HTTP_ERR_SIZE) {
5430 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5431 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005432 free(err);
5433 }
5434 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005435 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5436 int errnum, errlen, fd;
5437 char *err;
5438 struct stat stat;
5439
5440 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005441 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005442
5443 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005444 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005447 }
5448
5449 fd = open(args[2], O_RDONLY);
5450 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5451 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5452 file, linenum, args[2], args[1]);
5453 if (fd >= 0)
5454 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005457 }
5458
Willy Tarreau27a674e2009-08-17 07:23:33 +02005459 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005460 errlen = stat.st_size;
5461 } else {
5462 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005463 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005464 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005465 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005466 }
5467
5468 err = malloc(errlen); /* malloc() must succeed during parsing */
5469 errnum = read(fd, err, errlen);
5470 if (errnum != errlen) {
5471 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5472 file, linenum, args[2], args[1]);
5473 close(fd);
5474 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005477 }
5478 close(fd);
5479
5480 errnum = atol(args[1]);
5481 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5482 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005483 chunk_destroy(&curproxy->errmsg[rc]);
5484 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005485 break;
5486 }
5487 }
5488
5489 if (rc >= HTTP_ERR_SIZE) {
5490 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5491 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005492 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005493 free(err);
5494 }
5495 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005496 else if (!strcmp(args[0], "compression")) {
5497 struct comp *comp;
5498 if (curproxy->comp == NULL) {
5499 comp = calloc(1, sizeof(struct comp));
5500 curproxy->comp = comp;
5501 } else {
5502 comp = curproxy->comp;
5503 }
5504
5505 if (!strcmp(args[1], "algo")) {
5506 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005507 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005508
William Lallemand82fe75c2012-10-23 10:25:10 +02005509 cur_arg = 2;
5510 if (!*args[cur_arg]) {
5511 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5512 file, linenum, args[0]);
5513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
5515 }
5516 while (*(args[cur_arg])) {
5517 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5518 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5519 file, linenum, args[0], args[cur_arg]);
5520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522 }
William Lallemand552df672012-11-07 13:21:47 +01005523 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5524 curproxy->comp->algos->end(&ctx);
5525 } else {
5526 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5527 file, linenum, args[0], args[cur_arg]);
5528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
5530 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005531 cur_arg ++;
5532 continue;
5533 }
5534 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005535 else if (!strcmp(args[1], "offload")) {
5536 comp->offload = 1;
5537 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005538 else if (!strcmp(args[1], "type")) {
5539 int cur_arg;
5540 cur_arg = 2;
5541 if (!*args[cur_arg]) {
5542 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5543 file, linenum, args[0]);
5544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
5546 }
5547 while (*(args[cur_arg])) {
5548 comp_append_type(comp, args[cur_arg]);
5549 cur_arg ++;
5550 continue;
5551 }
5552 }
5553 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005554 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005555 file, linenum, args[0]);
5556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
5558 }
5559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005560 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005561 struct cfg_kw_list *kwl;
5562 int index;
5563
5564 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5565 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5566 if (kwl->kw[index].section != CFG_LISTEN)
5567 continue;
5568 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5569 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005570 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005571 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005572 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005575 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005576 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005577 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005578 err_code |= ERR_WARN;
5579 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005580 }
Willy Tarreau93893792009-07-23 13:19:11 +02005581 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005582 }
5583 }
5584 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005585
Willy Tarreau6daf3432008-01-22 16:44:08 +01005586 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 }
Willy Tarreau93893792009-07-23 13:19:11 +02005590 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005591 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593}
5594
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005595int
5596cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5597{
5598
5599 int err_code = 0;
5600 const char *err;
5601
5602 if (!strcmp(args[0], "userlist")) { /* new userlist */
5603 struct userlist *newul;
5604
5605 if (!*args[1]) {
5606 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5607 file, linenum, args[0]);
5608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
5610 }
5611
5612 err = invalid_char(args[1]);
5613 if (err) {
5614 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5615 file, linenum, *err, args[0], args[1]);
5616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
5618 }
5619
5620 for (newul = userlist; newul; newul = newul->next)
5621 if (!strcmp(newul->name, args[1])) {
5622 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5623 file, linenum, args[1]);
5624 err_code |= ERR_WARN;
5625 goto out;
5626 }
5627
5628 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5629 if (!newul) {
5630 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5631 err_code |= ERR_ALERT | ERR_ABORT;
5632 goto out;
5633 }
5634
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005635 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005636 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005637 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5638 err_code |= ERR_ALERT | ERR_ABORT;
5639 goto out;
5640 }
5641
5642 newul->next = userlist;
5643 userlist = newul;
5644
5645 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005646 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005647 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005648 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005649
5650 if (!*args[1]) {
5651 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5652 file, linenum, args[0]);
5653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
5655 }
5656
5657 err = invalid_char(args[1]);
5658 if (err) {
5659 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5660 file, linenum, *err, args[0], args[1]);
5661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
5663 }
5664
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005665 for (ag = userlist->groups; ag; ag = ag->next)
5666 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005667 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5668 file, linenum, args[1], userlist->name);
5669 err_code |= ERR_ALERT;
5670 goto out;
5671 }
5672
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005673 ag = calloc(1, sizeof(*ag));
5674 if (!ag) {
5675 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5676 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005677 goto out;
5678 }
5679
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005680 ag->name = strdup(args[1]);
5681 if (!ag) {
5682 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5683 err_code |= ERR_ALERT | ERR_ABORT;
5684 goto out;
5685 }
5686
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005687 cur_arg = 2;
5688
5689 while (*args[cur_arg]) {
5690 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005691 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005692 cur_arg += 2;
5693 continue;
5694 } else {
5695 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5696 file, linenum, args[0]);
5697 err_code |= ERR_ALERT | ERR_FATAL;
5698 goto out;
5699 }
5700 }
5701
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005702 ag->next = userlist->groups;
5703 userlist->groups = ag;
5704
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005705 } else if (!strcmp(args[0], "user")) { /* new user */
5706 struct auth_users *newuser;
5707 int cur_arg;
5708
5709 if (!*args[1]) {
5710 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5711 file, linenum, args[0]);
5712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
5714 }
5715
5716 for (newuser = userlist->users; newuser; newuser = newuser->next)
5717 if (!strcmp(newuser->user, args[1])) {
5718 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5719 file, linenum, args[1], userlist->name);
5720 err_code |= ERR_ALERT;
5721 goto out;
5722 }
5723
5724 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5725 if (!newuser) {
5726 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5727 err_code |= ERR_ALERT | ERR_ABORT;
5728 goto out;
5729 }
5730
5731 newuser->user = strdup(args[1]);
5732
5733 newuser->next = userlist->users;
5734 userlist->users = newuser;
5735
5736 cur_arg = 2;
5737
5738 while (*args[cur_arg]) {
5739 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005740#ifdef CONFIG_HAP_CRYPT
5741 if (!crypt("", args[cur_arg + 1])) {
5742 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5743 file, linenum, newuser->user);
5744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
5746 }
5747#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005748 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5749 file, linenum);
5750 err_code |= ERR_ALERT;
5751#endif
5752 newuser->pass = strdup(args[cur_arg + 1]);
5753 cur_arg += 2;
5754 continue;
5755 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5756 newuser->pass = strdup(args[cur_arg + 1]);
5757 newuser->flags |= AU_O_INSECURE;
5758 cur_arg += 2;
5759 continue;
5760 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005761 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005762 cur_arg += 2;
5763 continue;
5764 } else {
5765 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5766 file, linenum, args[0]);
5767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
5769 }
5770 }
5771 } else {
5772 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5773 err_code |= ERR_ALERT | ERR_FATAL;
5774 }
5775
5776out:
5777 return err_code;
5778}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779
5780/*
5781 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005782 * Returns the error code, 0 if OK, or any combination of :
5783 * - ERR_ABORT: must abort ASAP
5784 * - ERR_FATAL: we can continue parsing but not start the service
5785 * - ERR_WARN: a warning has been emitted
5786 * - ERR_ALERT: an alert has been emitted
5787 * Only the two first ones can stop processing, the two others are just
5788 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005790int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005792 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 FILE *f;
5794 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005795 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005796 struct cfg_section *cs = NULL;
5797 struct cfg_section *ics;
5798
5799 /* Register internal sections */
5800 if (!cfg_register_section("listen", cfg_parse_listen) ||
5801 !cfg_register_section("frontend", cfg_parse_listen) ||
5802 !cfg_register_section("backend", cfg_parse_listen) ||
5803 !cfg_register_section("ruleset", cfg_parse_listen) ||
5804 !cfg_register_section("defaults", cfg_parse_listen) ||
5805 !cfg_register_section("global", cfg_parse_global) ||
5806 !cfg_register_section("userlist", cfg_parse_users) ||
5807 !cfg_register_section("peers", cfg_parse_peers))
5808 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 if ((f=fopen(file,"r")) == NULL)
5811 return -1;
5812
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005813 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005814 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005815 char *end;
5816 char *args[MAX_LINE_ARGS + 1];
5817 char *line = thisline;
5818
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 linenum++;
5820
5821 end = line + strlen(line);
5822
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005823 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5824 /* Check if we reached the limit and the last char is not \n.
5825 * Watch out for the last line without the terminating '\n'!
5826 */
5827 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005828 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005829 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005830 }
5831
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005833 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 line++;
5835
5836 arg = 0;
5837 args[arg] = line;
5838
5839 while (*line && arg < MAX_LINE_ARGS) {
5840 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5841 * C equivalent value. Other combinations left unchanged (eg: \1).
5842 */
5843 if (*line == '\\') {
5844 int skip = 0;
5845 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5846 *line = line[1];
5847 skip = 1;
5848 }
5849 else if (line[1] == 'r') {
5850 *line = '\r';
5851 skip = 1;
5852 }
5853 else if (line[1] == 'n') {
5854 *line = '\n';
5855 skip = 1;
5856 }
5857 else if (line[1] == 't') {
5858 *line = '\t';
5859 skip = 1;
5860 }
5861 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005862 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 unsigned char hex1, hex2;
5864 hex1 = toupper(line[2]) - '0';
5865 hex2 = toupper(line[3]) - '0';
5866 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5867 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5868 *line = (hex1<<4) + hex2;
5869 skip = 3;
5870 }
5871 else {
5872 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005873 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 }
5875 }
5876 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005877 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 end -= skip;
5879 }
5880 line++;
5881 }
5882 else if (*line == '#' || *line == '\n' || *line == '\r') {
5883 /* end of string, end of loop */
5884 *line = 0;
5885 break;
5886 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005887 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005889 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005890 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 line++;
5892 args[++arg] = line;
5893 }
5894 else {
5895 line++;
5896 }
5897 }
5898
5899 /* empty line */
5900 if (!**args)
5901 continue;
5902
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005903 if (*line) {
5904 /* we had to stop due to too many args.
5905 * Let's terminate the string, print the offending part then cut the
5906 * last arg.
5907 */
5908 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5909 line++;
5910 *line = '\0';
5911
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005912 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005913 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 args[arg] = line;
5916 }
5917
Willy Tarreau540abe42007-05-02 20:50:16 +02005918 /* zero out remaining args and ensure that at least one entry
5919 * is zeroed out.
5920 */
5921 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 args[arg] = line;
5923 }
5924
Willy Tarreau3842f002009-06-14 11:39:52 +02005925 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005926 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005927 char *tmp;
5928
Willy Tarreau3842f002009-06-14 11:39:52 +02005929 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005930 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005931 for (arg=0; *args[arg+1]; arg++)
5932 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005933 *tmp = '\0'; // fix the next arg to \0
5934 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005935 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005936 else if (!strcmp(args[0], "default")) {
5937 kwm = KWM_DEF;
5938 for (arg=0; *args[arg+1]; arg++)
5939 args[arg] = args[arg+1]; // shift args after inversion
5940 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005941
William Lallemand0f99e342011-10-12 17:50:54 +02005942 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5943 strcmp(args[0], "log") != 0) {
5944 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005945 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005946 }
5947
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005948 /* detect section start */
5949 list_for_each_entry(ics, &sections, list) {
5950 if (strcmp(args[0], ics->section_name) == 0) {
5951 cursection = ics->section_name;
5952 cs = ics;
5953 break;
5954 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005955 }
5956
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005958 if (cs)
5959 err_code |= cs->section_parser(file, linenum, args, kwm);
5960 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005961 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005962 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005964
5965 if (err_code & ERR_ABORT)
5966 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005967 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005968 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005970 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005971}
5972
Willy Tarreau5436afc2014-09-16 12:17:36 +02005973/* This function propagates processes from frontend <from> to backend <to> so
5974 * that it is always guaranteed that a backend pointed to by a frontend is
5975 * bound to all of its processes. After that, if the target is a "listen"
5976 * instance, the function recursively descends the target's own targets along
5977 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
5978 * checked first to ensure that <to> is already bound to all processes of
5979 * <from>, there is no risk of looping and we ensure to follow the shortest
5980 * path to the destination.
5981 *
5982 * It is possible to set <to> to NULL for the first call so that the function
5983 * takes care of visiting the initial frontend in <from>.
5984 *
5985 * It is important to note that the function relies on the fact that all names
5986 * have already been resolved.
5987 */
5988void propagate_processes(struct proxy *from, struct proxy *to)
5989{
5990 struct switching_rule *rule;
5991 struct hdr_exp *exp;
5992
5993 if (to) {
5994 /* check whether we need to go down */
5995 if (from->bind_proc &&
5996 (from->bind_proc & to->bind_proc) == from->bind_proc)
5997 return;
5998
5999 if (!from->bind_proc && !to->bind_proc)
6000 return;
6001
6002 to->bind_proc = from->bind_proc ?
6003 (to->bind_proc | from->bind_proc) : 0;
6004
6005 /* now propagate down */
6006 from = to;
6007 }
6008
6009 if (!from->cap & PR_CAP_FE)
6010 return;
6011
6012 /* default_backend */
6013 if (from->defbe.be)
6014 propagate_processes(from, from->defbe.be);
6015
6016 /* use_backend */
6017 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006018 if (rule->dynamic)
6019 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006020 to = rule->be.backend;
6021 propagate_processes(from, to);
6022 }
6023
6024 /* reqsetbe */
6025 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6026 if (exp->action != ACT_SETBE)
6027 continue;
6028 to = (struct proxy *)exp->replace;
6029 propagate_processes(from, to);
6030 }
6031}
6032
Willy Tarreaubb925012009-07-23 13:36:36 +02006033/*
6034 * Returns the error code, 0 if OK, or any combination of :
6035 * - ERR_ABORT: must abort ASAP
6036 * - ERR_FATAL: we can continue parsing but not start the service
6037 * - ERR_WARN: a warning has been emitted
6038 * - ERR_ALERT: an alert has been emitted
6039 * Only the two first ones can stop processing, the two others are just
6040 * indicators.
6041 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006042int check_config_validity()
6043{
6044 int cfgerr = 0;
6045 struct proxy *curproxy = NULL;
6046 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006047 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006048 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006049 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006050
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006051 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 /*
6053 * Now, check for the integrity of all that we have collected.
6054 */
6055
6056 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006057 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058
Willy Tarreau193b8c62012-11-22 00:17:38 +01006059 if (!global.tune.max_http_hdr)
6060 global.tune.max_http_hdr = MAX_HTTP_HDR;
6061
6062 if (!global.tune.cookie_len)
6063 global.tune.cookie_len = CAPTURE_LEN;
6064
6065 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6066
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006067 /* Post initialisation of the users and groups lists. */
6068 err_code = userlist_postinit();
6069 if (err_code != ERR_NONE)
6070 goto out;
6071
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006072 /* first, we will invert the proxy list order */
6073 curproxy = NULL;
6074 while (proxy) {
6075 struct proxy *next;
6076
6077 next = proxy->next;
6078 proxy->next = curproxy;
6079 curproxy = proxy;
6080 if (!next)
6081 break;
6082 proxy = next;
6083 }
6084
Willy Tarreau91b00c22014-09-16 13:41:21 +02006085 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006086 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006087 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006088 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006089 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006090 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006091 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006092
Willy Tarreau050536d2012-10-04 08:47:34 +02006093 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006094 /* proxy ID not set, use automatic numbering with first
6095 * spare entry starting with next_pxid.
6096 */
6097 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6098 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6099 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006100 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006101 next_pxid++;
6102
Willy Tarreau55ea7572007-06-17 19:56:27 +02006103
Willy Tarreaubaaee002006-06-26 02:48:02 +02006104 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006105 /* ensure we don't keep listeners uselessly bound */
6106 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006107 continue;
6108 }
6109
Willy Tarreau102df612014-05-07 23:56:38 +02006110 /* Check multi-process mode compatibility for the current proxy */
6111
6112 if (curproxy->bind_proc) {
6113 /* an explicit bind-process was specified, let's check how many
6114 * processes remain.
6115 */
6116 nbproc = popcount(curproxy->bind_proc);
6117
6118 curproxy->bind_proc &= nbits(global.nbproc);
6119 if (!curproxy->bind_proc && nbproc == 1) {
6120 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);
6121 curproxy->bind_proc = 1;
6122 }
6123 else if (!curproxy->bind_proc && nbproc > 1) {
6124 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);
6125 curproxy->bind_proc = 0;
6126 }
6127 }
6128
Willy Tarreau3d209582014-05-09 17:06:11 +02006129 /* check and reduce the bind-proc of each listener */
6130 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6131 unsigned long mask;
6132
6133 if (!bind_conf->bind_proc)
6134 continue;
6135
6136 mask = nbits(global.nbproc);
6137 if (curproxy->bind_proc)
6138 mask &= curproxy->bind_proc;
6139 /* mask cannot be null here thanks to the previous checks */
6140
6141 nbproc = popcount(bind_conf->bind_proc);
6142 bind_conf->bind_proc &= mask;
6143
6144 if (!bind_conf->bind_proc && nbproc == 1) {
6145 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",
6146 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6147 bind_conf->bind_proc = mask & ~(mask - 1);
6148 }
6149 else if (!bind_conf->bind_proc && nbproc > 1) {
6150 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",
6151 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6152 bind_conf->bind_proc = 0;
6153 }
6154 }
6155
Willy Tarreau102df612014-05-07 23:56:38 +02006156 if (global.nbproc > 1 && curproxy->table.peers.name) {
6157 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6158 curproxy->id);
6159 cfgerr++;
6160 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006161
Willy Tarreauff01a212009-03-15 13:46:16 +01006162 switch (curproxy->mode) {
6163 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006164 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006165 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006166 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6167 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006168 cfgerr++;
6169 }
6170
6171 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006172 Warning("config : servers will be ignored for %s '%s'.\n",
6173 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006174 break;
6175
6176 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006177 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006178 break;
6179
6180 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006181 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006182 break;
6183 }
6184
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006185 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006186 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006187 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006188 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6189 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006190 cfgerr++;
6191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006193 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006194 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6195 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006196 cfgerr++;
6197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006199 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006200 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6201 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006202 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006203 }
6204 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006205 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006206 /* If no LB algo is set in a backend, and we're not in
6207 * transparent mode, dispatch mode nor proxy mode, we
6208 * want to use balance roundrobin by default.
6209 */
6210 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6211 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006212 }
6213 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006214
Willy Tarreau1620ec32011-08-06 17:05:02 +02006215 if (curproxy->options & PR_O_DISPATCH)
6216 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6217 else if (curproxy->options & PR_O_HTTP_PROXY)
6218 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6219 else if (curproxy->options & PR_O_TRANSP)
6220 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006221
Willy Tarreau1620ec32011-08-06 17:05:02 +02006222 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6223 if (curproxy->options & PR_O_DISABLE404) {
6224 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6225 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6226 err_code |= ERR_WARN;
6227 curproxy->options &= ~PR_O_DISABLE404;
6228 }
6229 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6230 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6231 "send-state", proxy_type_str(curproxy), curproxy->id);
6232 err_code |= ERR_WARN;
6233 curproxy->options &= ~PR_O2_CHK_SNDST;
6234 }
Willy Tarreauef781042010-01-27 11:53:01 +01006235 }
6236
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006237 /* if a default backend was specified, let's find it */
6238 if (curproxy->defbe.name) {
6239 struct proxy *target;
6240
Alex Williams96532db2009-11-01 21:27:13 -05006241 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006242 if (!target) {
6243 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6244 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006245 cfgerr++;
6246 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006247 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6248 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006249 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006250 } else {
6251 free(curproxy->defbe.name);
6252 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006253
6254 /* Emit a warning if this proxy also has some servers */
6255 if (curproxy->srv) {
6256 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6257 curproxy->id);
6258 err_code |= ERR_WARN;
6259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
6261 }
6262
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006263 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006264 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6265 /* map jump target for ACT_SETBE in req_rep chain */
6266 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006267 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006268 struct proxy *target;
6269
Willy Tarreaua496b602006-12-17 23:15:24 +01006270 if (exp->action != ACT_SETBE)
6271 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006272
Alex Williams96532db2009-11-01 21:27:13 -05006273 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006274 if (!target) {
6275 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6276 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006277 cfgerr++;
6278 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006279 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6280 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006281 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006282 } else {
6283 free((void *)exp->replace);
6284 exp->replace = (const char *)target;
6285 }
6286 }
6287 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006288
6289 /* find the target proxy for 'use_backend' rules */
6290 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006291 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006292 struct logformat_node *node;
6293 char *pxname;
6294
6295 /* Try to parse the string as a log format expression. If the result
6296 * of the parsing is only one entry containing a simple string, then
6297 * it's a standard string corresponding to a static rule, thus the
6298 * parsing is cancelled and be.name is restored to be resolved.
6299 */
6300 pxname = rule->be.name;
6301 LIST_INIT(&rule->be.expr);
6302 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6303 curproxy->conf.args.file, curproxy->conf.args.line);
6304 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6305
6306 if (!LIST_ISEMPTY(&rule->be.expr)) {
6307 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6308 rule->dynamic = 1;
6309 free(pxname);
6310 continue;
6311 }
6312 /* simple string: free the expression and fall back to static rule */
6313 free(node->arg);
6314 free(node);
6315 }
6316
6317 rule->dynamic = 0;
6318 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006319
Alex Williams96532db2009-11-01 21:27:13 -05006320 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006321
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006322 if (!target) {
6323 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6324 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006325 cfgerr++;
6326 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006327 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6328 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006329 cfgerr++;
6330 } else {
6331 free((void *)rule->be.name);
6332 rule->be.backend = target;
6333 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006334 }
6335
Willy Tarreau5436afc2014-09-16 12:17:36 +02006336 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006337 list_for_each_entry(srule, &curproxy->server_rules, list) {
6338 struct server *target = findserver(curproxy, srule->srv.name);
6339
6340 if (!target) {
6341 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6342 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6343 cfgerr++;
6344 continue;
6345 }
6346 free((void *)srule->srv.name);
6347 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006348 }
6349
Emeric Brunb982a3d2010-01-04 15:45:53 +01006350 /* find the target table for 'stick' rules */
6351 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6352 struct proxy *target;
6353
Emeric Brun1d33b292010-01-04 15:47:17 +01006354 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6355 if (mrule->flags & STK_IS_STORE)
6356 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6357
Emeric Brunb982a3d2010-01-04 15:45:53 +01006358 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006359 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006360 else
6361 target = curproxy;
6362
6363 if (!target) {
6364 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6365 curproxy->id, mrule->table.name);
6366 cfgerr++;
6367 }
6368 else if (target->table.size == 0) {
6369 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6370 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6371 cfgerr++;
6372 }
Willy Tarreau12785782012-04-27 21:37:17 +02006373 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6374 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006375 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6376 cfgerr++;
6377 }
6378 else {
6379 free((void *)mrule->table.name);
6380 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006381 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006382 }
6383 }
6384
6385 /* find the target table for 'store response' rules */
6386 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6387 struct proxy *target;
6388
Emeric Brun1d33b292010-01-04 15:47:17 +01006389 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6390
Emeric Brunb982a3d2010-01-04 15:45:53 +01006391 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006392 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006393 else
6394 target = curproxy;
6395
6396 if (!target) {
6397 Alert("Proxy '%s': unable to find store table '%s'.\n",
6398 curproxy->id, mrule->table.name);
6399 cfgerr++;
6400 }
6401 else if (target->table.size == 0) {
6402 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6403 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6404 cfgerr++;
6405 }
Willy Tarreau12785782012-04-27 21:37:17 +02006406 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6407 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006408 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6409 cfgerr++;
6410 }
6411 else {
6412 free((void *)mrule->table.name);
6413 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006414 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006415 }
6416 }
6417
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006418 /* find the target table for 'tcp-request' layer 4 rules */
6419 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6420 struct proxy *target;
6421
Willy Tarreaub4c84932013-07-23 19:15:30 +02006422 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006423 continue;
6424
6425 if (trule->act_prm.trk_ctr.table.n)
6426 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6427 else
6428 target = curproxy;
6429
6430 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006431 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6432 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006433 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006434 cfgerr++;
6435 }
6436 else if (target->table.size == 0) {
6437 Alert("Proxy '%s': table '%s' used but not configured.\n",
6438 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6439 cfgerr++;
6440 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006441 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6442 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6443 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 +01006444 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006445 cfgerr++;
6446 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006447 else {
6448 free(trule->act_prm.trk_ctr.table.n);
6449 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006450 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006451 * to pass a list of counters to track and allocate them right here using
6452 * stktable_alloc_data_type().
6453 */
6454 }
6455 }
6456
Willy Tarreaud1f96522010-08-03 19:34:32 +02006457 /* find the target table for 'tcp-request' layer 6 rules */
6458 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6459 struct proxy *target;
6460
Willy Tarreaub4c84932013-07-23 19:15:30 +02006461 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006462 continue;
6463
6464 if (trule->act_prm.trk_ctr.table.n)
6465 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6466 else
6467 target = curproxy;
6468
6469 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006470 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6471 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006472 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006473 cfgerr++;
6474 }
6475 else if (target->table.size == 0) {
6476 Alert("Proxy '%s': table '%s' used but not configured.\n",
6477 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6478 cfgerr++;
6479 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006480 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6481 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6482 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 +01006483 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006484 cfgerr++;
6485 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006486 else {
6487 free(trule->act_prm.trk_ctr.table.n);
6488 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006489 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006490 * to pass a list of counters to track and allocate them right here using
6491 * stktable_alloc_data_type().
6492 */
6493 }
6494 }
6495
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006496 /* move any "block" rules at the beginning of the http-request rules */
6497 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6498 /* insert block_rules into http_req_rules at the beginning */
6499 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6500 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6501 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6502 curproxy->http_req_rules.n = curproxy->block_rules.n;
6503 LIST_INIT(&curproxy->block_rules);
6504 }
6505
Emeric Brun32da3c42010-09-23 18:39:19 +02006506 if (curproxy->table.peers.name) {
6507 struct peers *curpeers = peers;
6508
6509 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6510 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6511 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006512 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006513 break;
6514 }
6515 }
6516
6517 if (!curpeers) {
6518 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6519 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006520 free((void *)curproxy->table.peers.name);
6521 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006522 cfgerr++;
6523 }
6524 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006525 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6526 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006527 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006528 cfgerr++;
6529 }
6530 }
6531
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006532 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006533 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006534 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6535 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6536 "proxy", curproxy->id);
6537 cfgerr++;
6538 goto out_uri_auth_compat;
6539 }
6540
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006541 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006542 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006543 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006544 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006545
Willy Tarreau95fa4692010-02-01 13:05:50 +01006546 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6547 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006548
6549 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006550 uri_auth_compat_req[i++] = "realm";
6551 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6552 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006553
Willy Tarreau95fa4692010-02-01 13:05:50 +01006554 uri_auth_compat_req[i++] = "unless";
6555 uri_auth_compat_req[i++] = "{";
6556 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6557 uri_auth_compat_req[i++] = "}";
6558 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006559
Willy Tarreauff011f22011-01-06 17:51:27 +01006560 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6561 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006562 cfgerr++;
6563 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006564 }
6565
Willy Tarreauff011f22011-01-06 17:51:27 +01006566 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006567
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006568 if (curproxy->uri_auth->auth_realm) {
6569 free(curproxy->uri_auth->auth_realm);
6570 curproxy->uri_auth->auth_realm = NULL;
6571 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006572
6573 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006574 }
6575out_uri_auth_compat:
6576
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006577 /* compile the log format */
6578 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006579 if (curproxy->conf.logformat_string != default_http_log_format &&
6580 curproxy->conf.logformat_string != default_tcp_log_format &&
6581 curproxy->conf.logformat_string != clf_http_log_format)
6582 free(curproxy->conf.logformat_string);
6583 curproxy->conf.logformat_string = NULL;
6584 free(curproxy->conf.lfs_file);
6585 curproxy->conf.lfs_file = NULL;
6586 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006587 }
6588
Willy Tarreau62a61232013-04-12 18:13:46 +02006589 if (curproxy->conf.logformat_string) {
6590 curproxy->conf.args.ctx = ARGC_LOG;
6591 curproxy->conf.args.file = curproxy->conf.lfs_file;
6592 curproxy->conf.args.line = curproxy->conf.lfs_line;
6593 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006594 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006595 curproxy->conf.args.file = NULL;
6596 curproxy->conf.args.line = 0;
6597 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006598
Willy Tarreau62a61232013-04-12 18:13:46 +02006599 if (curproxy->conf.uniqueid_format_string) {
6600 curproxy->conf.args.ctx = ARGC_UIF;
6601 curproxy->conf.args.file = curproxy->conf.uif_file;
6602 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006603 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006604 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6605 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006606 curproxy->conf.args.file = NULL;
6607 curproxy->conf.args.line = 0;
6608 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006609
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006610 /* only now we can check if some args remain unresolved.
6611 * This must be done after the users and groups resolution.
6612 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006613 cfgerr += smp_resolve_args(curproxy);
6614 if (!cfgerr)
6615 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006616
Willy Tarreau2738a142006-07-08 17:28:09 +02006617 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006618 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006619 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006620 (!curproxy->timeout.connect ||
6621 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006622 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006623 " | While not properly invalid, you will certainly encounter various problems\n"
6624 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006625 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006626 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006627 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006628 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006629
Willy Tarreau1fa31262007-12-03 00:36:16 +01006630 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6631 * We must still support older configurations, so let's find out whether those
6632 * parameters have been set or must be copied from contimeouts.
6633 */
6634 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006635 if (!curproxy->timeout.tarpit ||
6636 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006637 /* tarpit timeout not set. We search in the following order:
6638 * default.tarpit, curr.connect, default.connect.
6639 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006640 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006641 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006642 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006643 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006644 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006645 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006646 }
6647 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006648 (!curproxy->timeout.queue ||
6649 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006650 /* queue timeout not set. We search in the following order:
6651 * default.queue, curr.connect, default.connect.
6652 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006653 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006654 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006655 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006656 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006657 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006658 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006659 }
6660 }
6661
Willy Tarreau1620ec32011-08-06 17:05:02 +02006662 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006663 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6664 curproxy->check_req = (char *)malloc(curproxy->check_len);
6665 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006666 }
6667
Willy Tarreau215663d2014-06-13 18:30:23 +02006668 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6669 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6670 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6671 proxy_type_str(curproxy), curproxy->id);
6672 err_code |= ERR_WARN;
6673 }
6674
Willy Tarreau193b8c62012-11-22 00:17:38 +01006675 /* ensure that cookie capture length is not too large */
6676 if (curproxy->capture_len >= global.tune.cookie_len) {
6677 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6678 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6679 err_code |= ERR_WARN;
6680 curproxy->capture_len = global.tune.cookie_len - 1;
6681 }
6682
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006683 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006684 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006685 curproxy->req_cap_pool = create_pool("ptrcap",
6686 curproxy->nb_req_cap * sizeof(char *),
6687 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006688 }
6689
6690 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006691 curproxy->rsp_cap_pool = create_pool("ptrcap",
6692 curproxy->nb_rsp_cap * sizeof(char *),
6693 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006694 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006695
Willy Tarreaubaaee002006-06-26 02:48:02 +02006696 /* first, we will invert the servers list order */
6697 newsrv = NULL;
6698 while (curproxy->srv) {
6699 struct server *next;
6700
6701 next = curproxy->srv->next;
6702 curproxy->srv->next = newsrv;
6703 newsrv = curproxy->srv;
6704 if (!next)
6705 break;
6706 curproxy->srv = next;
6707 }
6708
Willy Tarreau17edc812014-01-03 12:14:34 +01006709 /* Check that no server name conflicts. This causes trouble in the stats.
6710 * We only emit a warning for the first conflict affecting each server,
6711 * in order to avoid combinatory explosion if all servers have the same
6712 * name. We do that only for servers which do not have an explicit ID,
6713 * because these IDs were made also for distinguishing them and we don't
6714 * want to annoy people who correctly manage them.
6715 */
6716 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6717 struct server *other_srv;
6718
6719 if (newsrv->puid)
6720 continue;
6721
6722 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6723 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6724 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6725 newsrv->conf.file, newsrv->conf.line,
6726 proxy_type_str(curproxy), curproxy->id,
6727 newsrv->id, other_srv->conf.line);
6728 break;
6729 }
6730 }
6731 }
6732
Willy Tarreaudd701652010-05-25 23:03:02 +02006733 /* assign automatic UIDs to servers which don't have one yet */
6734 next_id = 1;
6735 newsrv = curproxy->srv;
6736 while (newsrv != NULL) {
6737 if (!newsrv->puid) {
6738 /* server ID not set, use automatic numbering with first
6739 * spare entry starting with next_svid.
6740 */
6741 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6742 newsrv->conf.id.key = newsrv->puid = next_id;
6743 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6744 }
6745 next_id++;
6746 newsrv = newsrv->next;
6747 }
6748
Willy Tarreau20697042007-11-15 23:26:18 +01006749 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006750 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006751
Willy Tarreau62c3be22012-01-20 13:12:32 +01006752 /*
6753 * If this server supports a maxconn parameter, it needs a dedicated
6754 * tasks to fill the emptied slots when a connection leaves.
6755 * Also, resolve deferred tracking dependency if needed.
6756 */
6757 newsrv = curproxy->srv;
6758 while (newsrv != NULL) {
6759 if (newsrv->minconn > newsrv->maxconn) {
6760 /* Only 'minconn' was specified, or it was higher than or equal
6761 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6762 * this will avoid further useless expensive computations.
6763 */
6764 newsrv->maxconn = newsrv->minconn;
6765 } else if (newsrv->maxconn && !newsrv->minconn) {
6766 /* minconn was not specified, so we set it to maxconn */
6767 newsrv->minconn = newsrv->maxconn;
6768 }
6769
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006770#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006771 if (newsrv->use_ssl || newsrv->check.use_ssl)
6772 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006773#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006774
Willy Tarreau2f075e92013-12-03 11:11:34 +01006775 /* set the check type on the server */
6776 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6777
Willy Tarreau62c3be22012-01-20 13:12:32 +01006778 if (newsrv->trackit) {
6779 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006780 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006781 char *pname, *sname;
6782
6783 pname = newsrv->trackit;
6784 sname = strrchr(pname, '/');
6785
6786 if (sname)
6787 *sname++ = '\0';
6788 else {
6789 sname = pname;
6790 pname = NULL;
6791 }
6792
6793 if (pname) {
6794 px = findproxy(pname, PR_CAP_BE);
6795 if (!px) {
6796 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6797 proxy_type_str(curproxy), curproxy->id,
6798 newsrv->id, pname);
6799 cfgerr++;
6800 goto next_srv;
6801 }
6802 } else
6803 px = curproxy;
6804
6805 srv = findserver(px, sname);
6806 if (!srv) {
6807 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6808 proxy_type_str(curproxy), curproxy->id,
6809 newsrv->id, sname);
6810 cfgerr++;
6811 goto next_srv;
6812 }
6813
Willy Tarreau32091232014-05-16 13:52:00 +02006814 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6815 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6816 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006817 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006818 "tracking as it does not have any check nor agent enabled.\n",
6819 proxy_type_str(curproxy), curproxy->id,
6820 newsrv->id, px->id, srv->id);
6821 cfgerr++;
6822 goto next_srv;
6823 }
6824
6825 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6826
6827 if (loop) {
6828 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6829 "belongs to a tracking chain looping back to %s/%s.\n",
6830 proxy_type_str(curproxy), curproxy->id,
6831 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006832 cfgerr++;
6833 goto next_srv;
6834 }
6835
6836 if (curproxy != px &&
6837 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6838 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6839 "tracking: disable-on-404 option inconsistency.\n",
6840 proxy_type_str(curproxy), curproxy->id,
6841 newsrv->id, px->id, srv->id);
6842 cfgerr++;
6843 goto next_srv;
6844 }
6845
6846 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006847 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006848 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006849 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006850 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006851 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006852 }
6853
6854 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006855 newsrv->tracknext = srv->trackers;
6856 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006857
6858 free(newsrv->trackit);
6859 newsrv->trackit = NULL;
6860 }
6861 next_srv:
6862 newsrv = newsrv->next;
6863 }
6864
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006865 /* We have to initialize the server lookup mechanism depending
6866 * on what LB algorithm was choosen.
6867 */
6868
6869 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6870 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6871 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006872 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6873 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6874 init_server_map(curproxy);
6875 } else {
6876 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6877 fwrr_init_server_groups(curproxy);
6878 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006879 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006880
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006881 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006882 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6883 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6884 fwlc_init_server_tree(curproxy);
6885 } else {
6886 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6887 fas_init_server_tree(curproxy);
6888 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006889 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006890
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006891 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006892 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6893 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6894 chash_init_server_tree(curproxy);
6895 } else {
6896 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6897 init_server_map(curproxy);
6898 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006899 break;
6900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006901
6902 if (curproxy->options & PR_O_LOGASAP)
6903 curproxy->to_log &= ~LW_BYTES;
6904
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006905 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006906 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006907 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6908 proxy_type_str(curproxy), curproxy->id);
6909 err_code |= ERR_WARN;
6910 }
6911
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006912 if (curproxy->mode != PR_MODE_HTTP) {
6913 int optnum;
6914
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006915 if (curproxy->uri_auth) {
6916 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6917 proxy_type_str(curproxy), curproxy->id);
6918 err_code |= ERR_WARN;
6919 curproxy->uri_auth = NULL;
6920 }
6921
Willy Tarreau87cf5142011-08-19 22:57:24 +02006922 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006923 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6924 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6925 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006926 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006927 }
6928
6929 if (curproxy->options & PR_O_ORGTO) {
6930 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6931 "originalto", proxy_type_str(curproxy), curproxy->id);
6932 err_code |= ERR_WARN;
6933 curproxy->options &= ~PR_O_ORGTO;
6934 }
6935
6936 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6937 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6938 (curproxy->cap & cfg_opts[optnum].cap) &&
6939 (curproxy->options & cfg_opts[optnum].val)) {
6940 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6941 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6942 err_code |= ERR_WARN;
6943 curproxy->options &= ~cfg_opts[optnum].val;
6944 }
6945 }
6946
6947 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6948 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6949 (curproxy->cap & cfg_opts2[optnum].cap) &&
6950 (curproxy->options2 & cfg_opts2[optnum].val)) {
6951 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6952 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6953 err_code |= ERR_WARN;
6954 curproxy->options2 &= ~cfg_opts2[optnum].val;
6955 }
6956 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006957
Pieter Baauwd551fb52013-05-08 22:49:23 +02006958#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006959 if (curproxy->conn_src.bind_hdr_occ) {
6960 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006961 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006962 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006963 err_code |= ERR_WARN;
6964 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006965#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006966 }
6967
Willy Tarreaubaaee002006-06-26 02:48:02 +02006968 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006969 * ensure that we're not cross-dressing a TCP server into HTTP.
6970 */
6971 newsrv = curproxy->srv;
6972 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006973 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006974 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6975 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006976 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006977 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006978
Willy Tarreau0cec3312011-10-31 13:49:26 +01006979 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6980 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6981 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6982 err_code |= ERR_WARN;
6983 }
6984
Willy Tarreauc93cd162014-05-13 15:54:22 +02006985 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006986 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6987 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6988 err_code |= ERR_WARN;
6989 }
6990
Pieter Baauwd551fb52013-05-08 22:49:23 +02006991#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006992 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6993 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006994 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 +01006995 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006996 err_code |= ERR_WARN;
6997 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006998#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006999 newsrv = newsrv->next;
7000 }
7001
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007002 /* check if we have a frontend with "tcp-request content" looking at L7
7003 * with no inspect-delay
7004 */
7005 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7006 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7007 if (trule->action == TCP_ACT_CAPTURE &&
7008 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7009 break;
7010 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7011 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7012 break;
7013 }
7014
7015 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7016 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7017 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7018 " This means that these rules will randomly find their contents. This can be fixed by"
7019 " setting the tcp-request inspect-delay.\n",
7020 proxy_type_str(curproxy), curproxy->id);
7021 err_code |= ERR_WARN;
7022 }
7023 }
7024
Willy Tarreauc1a21672009-08-16 22:37:44 +02007025 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007026 if (!curproxy->accept)
7027 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007028
Willy Tarreauc1a21672009-08-16 22:37:44 +02007029 if (curproxy->tcp_req.inspect_delay ||
7030 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007031 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007032
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007033 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007034 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007035 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007036 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007037
7038 /* both TCP and HTTP must check switching rules */
7039 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7040 }
7041
7042 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007043 if (curproxy->tcp_req.inspect_delay ||
7044 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7045 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7046
Emeric Brun97679e72010-09-23 17:56:44 +02007047 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7048 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7049
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007050 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007051 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007052 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007053 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007054
7055 /* If the backend does requires RDP cookie persistence, we have to
7056 * enable the corresponding analyser.
7057 */
7058 if (curproxy->options2 & PR_O2_RDPC_PRST)
7059 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7060 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007061 }
7062
7063 /***********************************************************/
7064 /* At this point, target names have already been resolved. */
7065 /***********************************************************/
7066
7067 /* Check multi-process mode compatibility */
7068
7069 if (global.nbproc > 1 && global.stats_fe) {
7070 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7071 unsigned long mask;
7072
7073 mask = nbits(global.nbproc);
7074 if (global.stats_fe->bind_proc)
7075 mask &= global.stats_fe->bind_proc;
7076
7077 if (bind_conf->bind_proc)
7078 mask &= bind_conf->bind_proc;
7079
7080 /* stop here if more than one process is used */
7081 if (popcount(mask) > 1)
7082 break;
7083 }
7084 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7085 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");
7086 }
7087 }
7088
7089 /* Make each frontend inherit bind-process from its listeners when not specified. */
7090 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7091 if (curproxy->bind_proc)
7092 continue;
7093
7094 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7095 unsigned long mask;
7096
7097 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7098 curproxy->bind_proc |= mask;
7099 }
7100
7101 if (!curproxy->bind_proc)
7102 curproxy->bind_proc = ~0UL;
7103 }
7104
7105 if (global.stats_fe) {
7106 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7107 unsigned long mask;
7108
7109 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7110 global.stats_fe->bind_proc |= mask;
7111 }
7112 if (!global.stats_fe->bind_proc)
7113 global.stats_fe->bind_proc = ~0UL;
7114 }
7115
Willy Tarreaub3228c82014-10-01 20:50:17 +02007116 /* propagate bindings from frontends to backends. Don't do it if there
7117 * are any fatal errors as we must not call it with unresolved proxies.
7118 */
7119 if (!cfgerr) {
7120 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7121 if (curproxy->cap & PR_CAP_FE)
7122 propagate_processes(curproxy, NULL);
7123 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007124 }
7125
7126 /* Bind each unbound backend to all processes when not specified. */
7127 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7128 if (curproxy->bind_proc)
7129 continue;
7130 curproxy->bind_proc = ~0UL;
7131 }
7132
7133 /*******************************************************/
7134 /* At this step, all proxies have a non-null bind_proc */
7135 /*******************************************************/
7136
7137 /* perform the final checks before creating tasks */
7138
7139 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7140 struct listener *listener;
7141 unsigned int next_id;
7142 int nbproc;
7143
7144 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007145
Emeric Brunc52962f2012-11-15 18:28:02 +01007146#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007147 /* Configure SSL for each bind line.
7148 * Note: if configuration fails at some point, the ->ctx member
7149 * remains NULL so that listeners can later detach.
7150 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007151 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007152 int alloc_ctx;
7153
Emeric Brunc52962f2012-11-15 18:28:02 +01007154 if (!bind_conf->is_ssl) {
7155 if (bind_conf->default_ctx) {
7156 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7157 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7158 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007159 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007160 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007161 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007162 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007163 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007164 cfgerr++;
7165 continue;
7166 }
7167
Emeric Brun8dc60392014-05-09 13:52:00 +02007168 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007169 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007170 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7171 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");
7172 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007173 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007174 cfgerr++;
7175 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007176 }
7177
Emeric Brunfc0421f2012-09-07 17:30:07 +02007178 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007179 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007180 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007181#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007182
Willy Tarreaue6b98942007-10-29 01:09:36 +01007183 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007184 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007185 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007186 if (!listener->luid) {
7187 /* listener ID not set, use automatic numbering with first
7188 * spare entry starting with next_luid.
7189 */
7190 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7191 listener->conf.id.key = listener->luid = next_id;
7192 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007193 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007194 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007195
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007196 /* enable separate counters */
7197 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7198 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007199 if (!listener->name)
7200 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007201 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007202
Willy Tarreaue6b98942007-10-29 01:09:36 +01007203 if (curproxy->options & PR_O_TCP_NOLING)
7204 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007205 if (!listener->maxconn)
7206 listener->maxconn = curproxy->maxconn;
7207 if (!listener->backlog)
7208 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007209 if (!listener->maxaccept)
7210 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7211
7212 /* we want to have an optimal behaviour on single process mode to
7213 * maximize the work at once, but in multi-process we want to keep
7214 * some fairness between processes, so we target half of the max
7215 * number of events to be balanced over all the processes the proxy
7216 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7217 * used to disable the limit.
7218 */
7219 if (listener->maxaccept > 0) {
7220 if (nbproc > 1)
7221 listener->maxaccept = (listener->maxaccept + 1) / 2;
7222 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7223 }
7224
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007225 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007226 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007227 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007228 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007229
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007230 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7231 listener->options |= LI_O_TCP_RULES;
7232
Willy Tarreaude3041d2010-05-31 10:56:17 +02007233 if (curproxy->mon_mask.s_addr)
7234 listener->options |= LI_O_CHK_MONNET;
7235
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007236 /* smart accept mode is automatic in HTTP mode */
7237 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007238 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007239 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7240 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007241 }
7242
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007243 /* Release unused SSL configs */
7244 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7245 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007246 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007247#ifdef USE_OPENSSL
7248 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007249 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007250 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007251 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007252 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007253#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007254 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007255
Willy Tarreau102df612014-05-07 23:56:38 +02007256 if (nbproc > 1) {
7257 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007258 int count, maxproc = 0;
7259
7260 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7261 count = popcount(bind_conf->bind_proc);
7262 if (count > maxproc)
7263 maxproc = count;
7264 }
7265 /* backends have 0, frontends have 1 or more */
7266 if (maxproc != 1)
7267 Warning("Proxy '%s': in multi-process mode, stats will be"
7268 " limited to process assigned to the current request.\n",
7269 curproxy->id);
7270
Willy Tarreau102df612014-05-07 23:56:38 +02007271 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7272 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7273 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007274 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007275 }
Willy Tarreau102df612014-05-07 23:56:38 +02007276 if (curproxy->appsession_name) {
7277 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7278 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007279 }
Willy Tarreau102df612014-05-07 23:56:38 +02007280 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7281 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7282 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007283 }
7284 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007285
7286 /* create the task associated with the proxy */
7287 curproxy->task = task_new();
7288 if (curproxy->task) {
7289 curproxy->task->context = curproxy;
7290 curproxy->task->process = manage_proxy;
7291 /* no need to queue, it will be done automatically if some
7292 * listener gets limited.
7293 */
7294 curproxy->task->expire = TICK_ETERNITY;
7295 } else {
7296 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7297 curproxy->id);
7298 cfgerr++;
7299 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007300 }
7301
Willy Tarreaufbb78422011-06-05 15:38:35 +02007302 /* automatically compute fullconn if not set. We must not do it in the
7303 * loop above because cross-references are not yet fully resolved.
7304 */
7305 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7306 /* If <fullconn> is not set, let's set it to 10% of the sum of
7307 * the possible incoming frontend's maxconns.
7308 */
7309 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7310 struct proxy *fe;
7311 int total = 0;
7312
7313 /* sum up the number of maxconns of frontends which
7314 * reference this backend at least once or which are
7315 * the same one ('listen').
7316 */
7317 for (fe = proxy; fe; fe = fe->next) {
7318 struct switching_rule *rule;
7319 struct hdr_exp *exp;
7320 int found = 0;
7321
7322 if (!(fe->cap & PR_CAP_FE))
7323 continue;
7324
7325 if (fe == curproxy) /* we're on a "listen" instance */
7326 found = 1;
7327
7328 if (fe->defbe.be == curproxy) /* "default_backend" */
7329 found = 1;
7330
7331 /* check if a "use_backend" rule matches */
7332 if (!found) {
7333 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007334 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007335 found = 1;
7336 break;
7337 }
7338 }
7339 }
7340
7341 /* check if a "reqsetbe" rule matches */
7342 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7343 if (exp->action == ACT_SETBE &&
7344 (struct proxy *)exp->replace == curproxy) {
7345 found = 1;
7346 break;
7347 }
7348 }
7349
7350 /* now we've checked all possible ways to reference a backend
7351 * from a frontend.
7352 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007353 if (!found)
7354 continue;
7355 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007356 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007357 /* we have the sum of the maxconns in <total>. We only
7358 * keep 10% of that sum to set the default fullconn, with
7359 * a hard minimum of 1 (to avoid a divide by zero).
7360 */
7361 curproxy->fullconn = (total + 9) / 10;
7362 if (!curproxy->fullconn)
7363 curproxy->fullconn = 1;
7364 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007365 }
7366
Willy Tarreau056f5682010-06-06 15:51:11 +02007367 /* initialize stick-tables on backend capable proxies. This must not
7368 * be done earlier because the data size may be discovered while parsing
7369 * other proxies.
7370 */
Godbach9703e662013-12-11 21:11:41 +08007371 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007372 if (curproxy->state == PR_STSTOPPED)
7373 continue;
7374
Godbach9703e662013-12-11 21:11:41 +08007375 if (!stktable_init(&curproxy->table)) {
7376 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7377 cfgerr++;
7378 }
7379 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007380
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007381 /*
7382 * Recount currently required checks.
7383 */
7384
7385 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7386 int optnum;
7387
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007388 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7389 if (curproxy->options & cfg_opts[optnum].val)
7390 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007391
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007392 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7393 if (curproxy->options2 & cfg_opts2[optnum].val)
7394 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007395 }
7396
Willy Tarreau122541c2011-09-07 21:24:49 +02007397 if (peers) {
7398 struct peers *curpeers = peers, **last;
7399 struct peer *p, *pb;
7400
7401 /* Remove all peers sections which don't have a valid listener.
7402 * This can happen when a peers section is never referenced and
7403 * does not contain a local peer.
7404 */
7405 last = &peers;
7406 while (*last) {
7407 curpeers = *last;
7408 if (curpeers->peers_fe) {
7409 last = &curpeers->next;
7410 continue;
7411 }
7412
7413 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7414 curpeers->id, localpeer);
7415
7416 p = curpeers->remote;
7417 while (p) {
7418 pb = p->next;
7419 free(p->id);
7420 free(p);
7421 p = pb;
7422 }
7423
7424 /* Destroy and unlink this curpeers section.
7425 * Note: curpeers is backed up into *last.
7426 */
7427 free(curpeers->id);
7428 curpeers = curpeers->next;
7429 free(*last);
7430 *last = curpeers;
7431 }
7432 }
7433
Willy Tarreau34eb6712011-10-24 18:15:04 +02007434 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007435 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007436 MEM_F_SHARED);
7437
Willy Tarreaubb925012009-07-23 13:36:36 +02007438 if (cfgerr > 0)
7439 err_code |= ERR_ALERT | ERR_FATAL;
7440 out:
7441 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007442}
7443
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007444/*
7445 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7446 * parsing sessions.
7447 */
7448void cfg_register_keywords(struct cfg_kw_list *kwl)
7449{
7450 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7451}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007452
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007453/*
7454 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7455 */
7456void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7457{
7458 LIST_DEL(&kwl->list);
7459 LIST_INIT(&kwl->list);
7460}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007461
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007462/* this function register new section in the haproxy configuration file.
7463 * <section_name> is the name of this new section and <section_parser>
7464 * is the called parser. If two section declaration have the same name,
7465 * only the first declared is used.
7466 */
7467int cfg_register_section(char *section_name,
7468 int (*section_parser)(const char *, int, char **, int))
7469{
7470 struct cfg_section *cs;
7471
7472 cs = calloc(1, sizeof(*cs));
7473 if (!cs) {
7474 Alert("register section '%s': out of memory.\n", section_name);
7475 return 0;
7476 }
7477
7478 cs->section_name = section_name;
7479 cs->section_parser = section_parser;
7480
7481 LIST_ADDQ(&sections, &cs->list);
7482
7483 return 1;
7484}
7485
Willy Tarreaubaaee002006-06-26 02:48:02 +02007486/*
7487 * Local variables:
7488 * c-indent-level: 8
7489 * c-basic-offset: 8
7490 * End:
7491 */