blob: e04eff8eaaac297ae04f9553dbfe78951d963bda [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté2c8d7002014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau1c3a6122015-05-01 15:37:53 +0200154 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
283 ss = *ss2;
284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200543 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 if (!strcmp(args[0], "global")) { /* new section */
546 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200549 else if (!strcmp(args[0], "ca-base")) {
550#ifdef USE_OPENSSL
551 if (global.ca_base != NULL) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.ca_base = strdup(args[1]);
562#else
563 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566#endif
567 }
568 else if (!strcmp(args[0], "crt-base")) {
569#ifdef USE_OPENSSL
570 if (global.crt_base != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT;
573 goto out;
574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.crt_base = strdup(args[1]);
581#else
582 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585#endif
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 else if (!strcmp(args[0], "daemon")) {
588 global.mode |= MODE_DAEMON;
589 }
590 else if (!strcmp(args[0], "debug")) {
591 global.mode |= MODE_DEBUG;
592 }
593 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100594 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200596 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100602 else if (!strcmp(args[0], "nosplice")) {
603 global.tune.options &= ~GTUNE_USE_SPLICE;
604 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605 else if (!strcmp(args[0], "nogetaddrinfo")) {
606 global.tune.options &= ~GTUNE_USE_GAI;
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "quiet")) {
609 global.mode |= MODE_QUIET;
610 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200611 else if (!strcmp(args[0], "tune.maxpollevents")) {
612 if (global.tune.maxpollevents != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200621 }
622 global.tune.maxpollevents = atol(args[1]);
623 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100624 else if (!strcmp(args[0], "tune.maxaccept")) {
625 if (global.tune.maxaccept != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100634 }
635 global.tune.maxaccept = atol(args[1]);
636 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200637 else if (!strcmp(args[0], "tune.chksize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.chksize = atol(args[1]);
644 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200645#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200646 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
647 global.tune.sslprivatecache = 1;
648 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100649 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.sslcachesize = atol(args[1]);
656 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100657 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
658 unsigned int ssllifetime;
659 const char *res;
660
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666
667 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
668 if (res) {
669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
670 file, linenum, *res, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 global.tune.ssllifetime = ssllifetime;
676 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100677 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.ssl_max_record = atol(args[1]);
684 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200685 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.ssl_default_dh_param = atol(args[1]);
692 if (global.tune.ssl_default_dh_param < 1024) {
693 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200698#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200699 else if (!strcmp(args[0], "tune.bufsize")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.bufsize = atol(args[1]);
706 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
707 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100708 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100709 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200710 }
711 else if (!strcmp(args[0], "tune.maxrewrite")) {
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 global.tune.maxrewrite = atol(args[1]);
718 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
719 global.tune.maxrewrite = global.tune.bufsize / 2;
720 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100721 else if (!strcmp(args[0], "tune.idletimer")) {
722 unsigned int idle;
723 const char *res;
724
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730
731 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
732 if (res) {
733 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
734 file, linenum, *res, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738
739 if (idle > 65535) {
740 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.idle_timer = idle;
745 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100746 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
747 if (global.tune.client_rcvbuf != 0) {
748 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
749 err_code |= ERR_ALERT;
750 goto out;
751 }
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757 global.tune.client_rcvbuf = atol(args[1]);
758 }
759 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
760 if (global.tune.server_rcvbuf != 0) {
761 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT;
763 goto out;
764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.server_rcvbuf = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "tune.sndbuf.client")) {
773 if (global.tune.client_sndbuf != 0) {
774 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT;
776 goto out;
777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.client_sndbuf = atol(args[1]);
784 }
785 else if (!strcmp(args[0], "tune.sndbuf.server")) {
786 if (global.tune.server_sndbuf != 0) {
787 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT;
789 goto out;
790 }
791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.tune.server_sndbuf = atol(args[1]);
797 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200798 else if (!strcmp(args[0], "tune.pipesize")) {
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.pipesize = atol(args[1]);
805 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100806 else if (!strcmp(args[0], "tune.http.cookielen")) {
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.cookie_len = atol(args[1]) + 1;
813 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200814 else if (!strcmp(args[0], "tune.http.maxhdr")) {
815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.tune.max_http_hdr = atol(args[1]);
821 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100822 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
823#ifdef USE_ZLIB
824 if (*args[1]) {
825 global.tune.zlibmemlevel = atoi(args[1]);
826 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 } else {
833 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
834 file, linenum, args[0]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838#else
839 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842#endif
843 }
844 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
845#ifdef USE_ZLIB
846 if (*args[1]) {
847 global.tune.zlibwindowsize = atoi(args[1]);
848 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
849 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
850 file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 } else {
855 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
856 file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860#else
861 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864#endif
865 }
William Lallemandf3747832012-11-09 12:33:10 +0100866 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
867 if (*args[1]) {
868 global.tune.comp_maxlevel = atoi(args[1]);
869 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
870 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
871 file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 } else {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 else if (!strcmp(args[0], "uid")) {
883 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200884 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT;
886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 global.uid = atol(args[1]);
894 }
895 else if (!strcmp(args[0], "gid")) {
896 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200897 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 global.gid = atol(args[1]);
907 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200908 /* user/group name handling */
909 else if (!strcmp(args[0], "user")) {
910 struct passwd *ha_user;
911 if (global.uid != 0) {
912 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200913 err_code |= ERR_ALERT;
914 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200915 }
916 errno = 0;
917 ha_user = getpwnam(args[1]);
918 if (ha_user != NULL) {
919 global.uid = (int)ha_user->pw_uid;
920 }
921 else {
922 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200923 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200924 }
925 }
926 else if (!strcmp(args[0], "group")) {
927 struct group *ha_group;
928 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200929 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT;
931 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200932 }
933 errno = 0;
934 ha_group = getgrnam(args[1]);
935 if (ha_group != NULL) {
936 global.gid = (int)ha_group->gr_gid;
937 }
938 else {
939 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200941 }
942 }
943 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100951 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
952 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
953 file, linenum, args[0], LONGBITS, global.nbproc);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (!strcmp(args[0], "maxconn")) {
959 if (global.maxconn != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT;
962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 global.maxconn = atol(args[1]);
970#ifdef SYSTEM_MAXCONN
971 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
972 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
973 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200974 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 }
976#endif /* SYSTEM_MAXCONN */
977 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200978 else if (!strcmp(args[0], "maxsslconn")) {
979#ifdef USE_OPENSSL
980 if (*(args[1]) == 0) {
981 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984 }
985 global.maxsslconn = atol(args[1]);
986#else
Emeric Brun0914df82012-10-02 18:45:42 +0200987 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200990#endif
991 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100992 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
993#ifdef USE_OPENSSL
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999 free(global.listen_default_ciphers);
1000 global.listen_default_ciphers = strdup(args[1]);
1001#else
1002 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005#endif
1006 }
1007 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1008#ifdef USE_OPENSSL
1009 if (*(args[1]) == 0) {
1010 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 free(global.connect_default_ciphers);
1015 global.connect_default_ciphers = strdup(args[1]);
1016#else
1017 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020#endif
1021 }
Emeric Brun850efd52014-01-29 12:24:34 +01001022 else if (!strcmp(args[0], "ssl-server-verify")) {
1023 if (*(args[1]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 if (strcmp(args[1],"none") == 0)
1029 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1030 else if (strcmp(args[1],"required") == 0)
1031 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1032 else {
1033 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036 }
1037 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001038 else if (!strcmp(args[0], "maxconnrate")) {
1039 if (global.cps_lim != 0) {
1040 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT;
1042 goto out;
1043 }
1044 if (*(args[1]) == 0) {
1045 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
1048 }
1049 global.cps_lim = atol(args[1]);
1050 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001051 else if (!strcmp(args[0], "maxsessrate")) {
1052 if (global.sps_lim != 0) {
1053 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1054 err_code |= ERR_ALERT;
1055 goto out;
1056 }
1057 if (*(args[1]) == 0) {
1058 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 global.sps_lim = atol(args[1]);
1063 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001064 else if (!strcmp(args[0], "maxsslrate")) {
1065 if (global.ssl_lim != 0) {
1066 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1067 err_code |= ERR_ALERT;
1068 goto out;
1069 }
1070 if (*(args[1]) == 0) {
1071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 global.ssl_lim = atol(args[1]);
1076 }
William Lallemandd85f9172012-11-09 17:05:39 +01001077 else if (!strcmp(args[0], "maxcomprate")) {
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
1082 }
1083 global.comp_rate_lim = atoi(args[1]) * 1024;
1084 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001085 else if (!strcmp(args[0], "maxpipes")) {
1086 if (global.maxpipes != 0) {
1087 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT;
1089 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001090 }
1091 if (*(args[1]) == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001095 }
1096 global.maxpipes = atol(args[1]);
1097 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001098 else if (!strcmp(args[0], "maxzlibmem")) {
1099 if (*(args[1]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
William Lallemande3a7d992012-11-20 11:25:20 +01001104 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001105 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001106 else if (!strcmp(args[0], "maxcompcpuusage")) {
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001113 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001114 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT | ERR_FATAL;
1116 goto out;
1117 }
1118}
1119
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 else if (!strcmp(args[0], "ulimit-n")) {
1121 if (global.rlimit_nofile != 0) {
1122 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 }
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 global.rlimit_nofile = atol(args[1]);
1132 }
1133 else if (!strcmp(args[0], "chroot")) {
1134 if (global.chroot != NULL) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
1137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 global.chroot = strdup(args[1]);
1145 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001146 else if (!strcmp(args[0], "description")) {
1147 int i, len=0;
1148 char *d;
1149
1150 if (!*args[1]) {
1151 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1152 file, linenum, args[0]);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto out;
1155 }
1156
Willy Tarreau348acfe2014-04-14 15:00:39 +02001157 for (i = 1; *args[i]; i++)
1158 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001159
1160 if (global.desc)
1161 free(global.desc);
1162
1163 global.desc = d = (char *)calloc(1, len);
1164
Willy Tarreau348acfe2014-04-14 15:00:39 +02001165 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1166 for (i = 2; *args[i]; i++)
1167 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001168 }
1169 else if (!strcmp(args[0], "node")) {
1170 int i;
1171 char c;
1172
1173 for (i=0; args[1][i]; i++) {
1174 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001175 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1176 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001177 break;
1178 }
1179
1180 if (!i || args[1][i]) {
1181 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1182 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1183 file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 if (global.node)
1189 free(global.node);
1190
1191 global.node = strdup(args[1]);
1192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 else if (!strcmp(args[0], "pidfile")) {
1194 if (global.pidfile != NULL) {
1195 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT;
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 }
1199 if (*(args[1]) == 0) {
1200 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 global.pidfile = strdup(args[1]);
1205 }
Emeric Bruned760922010-10-22 17:59:25 +02001206 else if (!strcmp(args[0], "unix-bind")) {
1207 int cur_arg = 1;
1208 while (*(args[cur_arg])) {
1209 if (!strcmp(args[cur_arg], "prefix")) {
1210 if (global.unix_bind.prefix != NULL) {
1211 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1212 err_code |= ERR_ALERT;
1213 cur_arg += 2;
1214 continue;
1215 }
1216
1217 if (*(args[cur_arg+1]) == 0) {
1218 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1223 cur_arg += 2;
1224 continue;
1225 }
1226
1227 if (!strcmp(args[cur_arg], "mode")) {
1228
1229 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1230 cur_arg += 2;
1231 continue;
1232 }
1233
1234 if (!strcmp(args[cur_arg], "uid")) {
1235
1236 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1237 cur_arg += 2;
1238 continue;
1239 }
1240
1241 if (!strcmp(args[cur_arg], "gid")) {
1242
1243 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1244 cur_arg += 2;
1245 continue;
1246 }
1247
1248 if (!strcmp(args[cur_arg], "user")) {
1249 struct passwd *user;
1250
1251 user = getpwnam(args[cur_arg + 1]);
1252 if (!user) {
1253 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1254 file, linenum, args[0], args[cur_arg + 1 ]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258
1259 global.unix_bind.ux.uid = user->pw_uid;
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (!strcmp(args[cur_arg], "group")) {
1265 struct group *group;
1266
1267 group = getgrnam(args[cur_arg + 1]);
1268 if (!group) {
1269 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1270 file, linenum, args[0], args[cur_arg + 1 ]);
1271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
1273 }
1274
1275 global.unix_bind.ux.gid = group->gr_gid;
1276 cur_arg += 2;
1277 continue;
1278 }
1279
Willy Tarreaub48f9582011-09-05 01:17:06 +02001280 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001281 file, linenum, args[0]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285 }
William Lallemand0f99e342011-10-12 17:50:54 +02001286 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1287 /* delete previous herited or defined syslog servers */
1288 struct logsrv *back;
1289 struct logsrv *tmp;
1290
1291 if (*(args[1]) != 0) {
1292 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
1296
1297 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1298 LIST_DEL(&tmp->list);
1299 free(tmp);
1300 }
1301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001303 struct sockaddr_storage *sk;
1304 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001305 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001306 int arg = 0;
1307 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001308
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 if (*(args[1]) == 0 || *(args[2]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313 }
William Lallemand0f99e342011-10-12 17:50:54 +02001314
1315 logsrv = calloc(1, sizeof(struct logsrv));
1316
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001317 /* just after the address, a length may be specified */
1318 if (strcmp(args[arg+2], "len") == 0) {
1319 len = atoi(args[arg+3]);
1320 if (len < 80 || len > 65535) {
1321 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1322 file, linenum, args[arg+3]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326 logsrv->maxlen = len;
1327
1328 /* skip these two args */
1329 arg += 2;
1330 }
1331 else
1332 logsrv->maxlen = MAX_SYSLOG_LEN;
1333
1334 if (logsrv->maxlen > global.max_syslog_len) {
1335 global.max_syslog_len = logsrv->maxlen;
1336 logline = realloc(logline, global.max_syslog_len + 1);
1337 }
1338
1339 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001340 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001341 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001343 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 }
1345
William Lallemand0f99e342011-10-12 17:50:54 +02001346 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001347 if (*(args[arg+3])) {
1348 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001349 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001350 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001352 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
1354 }
1355
William Lallemand0f99e342011-10-12 17:50:54 +02001356 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001357 if (*(args[arg+4])) {
1358 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001359 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001360 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001361 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001362 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001363 }
1364 }
1365
Willy Tarreau902636f2013-03-10 19:44:48 +01001366 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001367 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001368 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001369 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001370 free(logsrv);
1371 goto out;
1372 }
1373 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001374
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001375 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001376 if (port1 != port2) {
1377 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1378 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001379 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001380 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001381 goto out;
1382 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001383
William Lallemand0f99e342011-10-12 17:50:54 +02001384 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001385 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001386 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388
William Lallemand0f99e342011-10-12 17:50:54 +02001389 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001390 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001391 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1392 char *name;
1393 int len;
1394
1395 if (global.log_send_hostname != NULL) {
1396 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1397 err_code |= ERR_ALERT;
1398 goto out;
1399 }
1400
1401 if (*(args[1]))
1402 name = args[1];
1403 else
1404 name = hostname;
1405
1406 len = strlen(name);
1407
1408 /* We'll add a space after the name to respect the log format */
1409 free(global.log_send_hostname);
1410 global.log_send_hostname = malloc(len + 2);
1411 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1412 }
Kevinm48936af2010-12-22 16:08:21 +00001413 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1414 if (*(args[1]) == 0) {
1415 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1416 err_code |= ERR_ALERT | ERR_FATAL;
1417 goto out;
1418 }
1419 free(global.log_tag);
1420 global.log_tag = strdup(args[1]);
1421 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001422 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1423 if (global.spread_checks != 0) {
1424 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001425 err_code |= ERR_ALERT;
1426 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001427 }
1428 if (*(args[1]) == 0) {
1429 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001432 }
1433 global.spread_checks = atol(args[1]);
1434 if (global.spread_checks < 0 || global.spread_checks > 50) {
1435 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001439 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1440 const char *err;
1441 unsigned int val;
1442
1443
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449
1450 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1451 if (err) {
1452 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 }
1455 global.max_spread_checks = val;
1456 if (global.max_spread_checks < 0) {
1457 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1458 err_code |= ERR_ALERT | ERR_FATAL;
1459 }
1460 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001461 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1462#ifdef USE_CPU_AFFINITY
1463 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001464 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001465 unsigned long cpus = 0;
1466
1467 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001468 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001469 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001470 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001471 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001472 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001473 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001474 proc = atol(args[1]);
1475 if (proc >= 1 && proc <= LONGBITS)
1476 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001477 }
1478
1479 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001480 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1481 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 cur_arg = 2;
1487 while (*args[cur_arg]) {
1488 unsigned int low, high;
1489
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001490 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001491 char *dash = strchr(args[cur_arg], '-');
1492
1493 low = high = str2uic(args[cur_arg]);
1494 if (dash)
1495 high = str2uic(dash + 1);
1496
1497 if (high < low) {
1498 unsigned int swap = low;
1499 low = high;
1500 high = swap;
1501 }
1502
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001503 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001504 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001505 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 while (low <= high)
1511 cpus |= 1UL << low++;
1512 }
1513 else {
1514 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1515 file, linenum, args[0], args[cur_arg]);
1516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
1518 }
1519 cur_arg++;
1520 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001521 for (i = 0; i < LONGBITS; i++)
1522 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001523 global.cpu_map[i] = cpus;
1524#else
1525 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1526 err_code |= ERR_ALERT | ERR_FATAL;
1527 goto out;
1528#endif
1529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001531 struct cfg_kw_list *kwl;
1532 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001533 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001534
1535 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1536 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1537 if (kwl->kw[index].section != CFG_GLOBAL)
1538 continue;
1539 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001540 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001541 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001542 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001544 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001545 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001546 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001547 err_code |= ERR_WARN;
1548 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001549 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001551 }
1552 }
1553 }
1554
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001556 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001558
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001560 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562}
1563
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001564void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001566 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 defproxy.mode = PR_MODE_TCP;
1568 defproxy.state = PR_STNEW;
1569 defproxy.maxconn = cfg_maxpconn;
1570 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001571
Simon Horman66183002013-02-23 10:16:43 +09001572 defproxy.defsrv.check.inter = DEF_CHKINTR;
1573 defproxy.defsrv.check.fastinter = 0;
1574 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001575 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1576 defproxy.defsrv.agent.fastinter = 0;
1577 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001578 defproxy.defsrv.check.rise = DEF_RISETIME;
1579 defproxy.defsrv.check.fall = DEF_FALLTIME;
1580 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1581 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001582 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001583 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001584 defproxy.defsrv.maxqueue = 0;
1585 defproxy.defsrv.minconn = 0;
1586 defproxy.defsrv.maxconn = 0;
1587 defproxy.defsrv.slowstart = 0;
1588 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1589 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1590 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591}
1592
Willy Tarreauade5ec42010-01-28 19:33:49 +01001593
Willy Tarreau63af98d2014-05-18 08:11:41 +02001594/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1595 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1596 * ERR_FATAL in case of error.
1597 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001598static int create_cond_regex_rule(const char *file, int line,
1599 struct proxy *px, int dir, int action, int flags,
1600 const char *cmd, const char *reg, const char *repl,
1601 const char **cond_start)
1602{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001603 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001604 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001605 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001606 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001607 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001608 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001609 int cs;
1610 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001611
1612 if (px == &defproxy) {
1613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001614 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001615 goto err;
1616 }
1617
1618 if (*reg == 0) {
1619 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001620 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001621 goto err;
1622 }
1623
1624 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001625 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001626
Willy Tarreau5321c422010-01-28 20:35:13 +01001627 if (cond_start &&
1628 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001629 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1630 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1631 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001632 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001633 goto err;
1634 }
1635 }
1636 else if (cond_start && **cond_start) {
1637 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1638 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001639 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001640 goto err;
1641 }
1642
Willy Tarreau63af98d2014-05-18 08:11:41 +02001643 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001644 (dir == SMP_OPT_DIR_REQ) ?
1645 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1646 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1647 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001648
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001649 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001650 if (!preg) {
1651 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001652 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001653 goto err;
1654 }
1655
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001656 cs = !(flags & REG_ICASE);
1657 cap = !(flags & REG_NOSUB);
1658 error = NULL;
1659 if (!regex_comp(reg, preg, cs, cap, &error)) {
1660 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1661 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001662 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001663 goto err;
1664 }
1665
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001666 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001667 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001668 if (repl && err) {
1669 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1670 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
1672 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001673 }
1674
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001675 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_WARN;
1677
1678 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001679
Willy Tarreau63af98d2014-05-18 08:11:41 +02001680 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001681 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682 err:
1683 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001684 free(errmsg);
1685 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001686}
1687
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001689 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001690 * Returns the error code, 0 if OK, or any combination of :
1691 * - ERR_ABORT: must abort ASAP
1692 * - ERR_FATAL: we can continue parsing but not start the service
1693 * - ERR_WARN: a warning has been emitted
1694 * - ERR_ALERT: an alert has been emitted
1695 * Only the two first ones can stop processing, the two others are just
1696 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001698int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1699{
1700 static struct peers *curpeers = NULL;
1701 struct peer *newpeer = NULL;
1702 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct bind_conf *bind_conf;
1704 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001705 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001706 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001707
1708 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001709 if (!*args[1]) {
1710 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001711 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001712 goto out;
1713 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001714
1715 err = invalid_char(args[1]);
1716 if (err) {
1717 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1718 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001719 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001720 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 }
1722
1723 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1724 /*
1725 * If there are two proxies with the same name only following
1726 * combinations are allowed:
1727 */
1728 if (strcmp(curpeers->id, args[1]) == 0) {
1729 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1730 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1731 err_code |= ERR_WARN;
1732 }
1733 }
1734
1735 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1736 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1737 err_code |= ERR_ALERT | ERR_ABORT;
1738 goto out;
1739 }
1740
1741 curpeers->next = peers;
1742 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001743 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001744 curpeers->conf.line = linenum;
1745 curpeers->last_change = now.tv_sec;
1746 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001747 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001748 }
1749 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001750 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001751 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001752 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001753
1754 if (!*args[2]) {
1755 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1756 file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
1760
1761 err = invalid_char(args[1]);
1762 if (err) {
1763 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1764 file, linenum, *err, args[1]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767 }
1768
1769 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1770 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1771 err_code |= ERR_ALERT | ERR_ABORT;
1772 goto out;
1773 }
1774
1775 /* the peers are linked backwards first */
1776 curpeers->count++;
1777 newpeer->next = curpeers->remote;
1778 curpeers->remote = newpeer;
1779 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001780 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001781 newpeer->conf.line = linenum;
1782
1783 newpeer->last_change = now.tv_sec;
1784 newpeer->id = strdup(args[1]);
1785
Willy Tarreau902636f2013-03-10 19:44:48 +01001786 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001787 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001788 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001791 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001792
1793 proto = protocol_by_family(sk->ss_family);
1794 if (!proto || !proto->connect) {
1795 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1796 file, linenum, args[0], args[1]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001800
1801 if (port1 != port2) {
1802 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1803 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001804 err_code |= ERR_ALERT | ERR_FATAL;
1805 goto out;
1806 }
1807
Willy Tarreau2aa38802013-02-20 19:20:59 +01001808 if (!port1) {
1809 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1810 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001814
Emeric Brun32da3c42010-09-23 18:39:19 +02001815 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001816 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001817 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001818 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001819
Emeric Brun32da3c42010-09-23 18:39:19 +02001820 if (strcmp(newpeer->id, localpeer) == 0) {
1821 /* Current is local peer, it define a frontend */
1822 newpeer->local = 1;
1823
1824 if (!curpeers->peers_fe) {
1825 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1826 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1827 err_code |= ERR_ALERT | ERR_ABORT;
1828 goto out;
1829 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001830
Willy Tarreau237250c2011-07-29 01:49:03 +02001831 init_new_proxy(curpeers->peers_fe);
1832 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001833
1834 curpeers->peers_fe->last_change = now.tv_sec;
1835 curpeers->peers_fe->id = strdup(args[1]);
1836 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001837 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001838 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001839 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001840 curpeers->peers_fe->accept = peer_accept;
1841 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001842 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1843 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001844
1845 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1846
Willy Tarreau902636f2013-03-10 19:44:48 +01001847 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1848 if (errmsg && *errmsg) {
1849 indent_msg(&errmsg, 2);
1850 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001851 }
1852 else
1853 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1854 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001855 err_code |= ERR_FATAL;
1856 goto out;
1857 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001858
1859 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001860 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001861 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1862 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1863 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1864 l->accept = session_accept;
1865 l->handler = process_session;
1866 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1867 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1868 global.maxsock += l->maxconn;
1869 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001870 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001871 else {
1872 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1873 file, linenum, args[0], args[1],
1874 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1875 err_code |= ERR_FATAL;
1876 goto out;
1877 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001878 }
1879 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001880 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1881 curpeers->state = PR_STSTOPPED;
1882 }
1883 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1884 curpeers->state = PR_STNEW;
1885 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001886 else if (*args[0] != 0) {
1887 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
1890 }
1891
1892out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001893 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001894 return err_code;
1895}
1896
Willy Tarreau3842f002009-06-14 11:39:52 +02001897int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898{
1899 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001900 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001901 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001902 int rc;
1903 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001904 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001905 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001906 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001907 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001908 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909
Willy Tarreau977b8e42006-12-29 14:19:17 +01001910 if (!strcmp(args[0], "listen"))
1911 rc = PR_CAP_LISTEN;
1912 else if (!strcmp(args[0], "frontend"))
1913 rc = PR_CAP_FE | PR_CAP_RS;
1914 else if (!strcmp(args[0], "backend"))
1915 rc = PR_CAP_BE | PR_CAP_RS;
1916 else if (!strcmp(args[0], "ruleset"))
1917 rc = PR_CAP_RS;
1918 else
1919 rc = PR_CAP_NONE;
1920
1921 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001922 struct ebpt_node *node;
1923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 if (!*args[1]) {
1925 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1926 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1927 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001928 err_code |= ERR_ALERT | ERR_ABORT;
1929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001931
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001932 err = invalid_char(args[1]);
1933 if (err) {
1934 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1935 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001937 }
1938
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001939 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1940 curproxy = container_of(node, struct proxy, conf.by_name);
1941
1942 if (strcmp(curproxy->id, args[1]) != 0)
1943 break;
1944
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001945 /*
1946 * If there are two proxies with the same name only following
1947 * combinations are allowed:
1948 *
1949 * listen backend frontend ruleset
1950 * listen - - - -
1951 * backend - - OK -
1952 * frontend - OK - -
1953 * ruleset - - - -
1954 */
1955
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001956 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1957 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001958 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1959 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1960 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001962 }
1963 }
1964
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1966 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_ABORT;
1968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001970
Willy Tarreau97cb7802010-01-03 20:23:58 +01001971 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 curproxy->next = proxy;
1973 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001974 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1975 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001976 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001978 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001979 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980
1981 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001982 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001983 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001984
Willy Tarreau4348fad2012-09-20 16:48:07 +02001985 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1986
Willy Tarreau902636f2013-03-10 19:44:48 +01001987 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1988 if (errmsg && *errmsg) {
1989 indent_msg(&errmsg, 2);
1990 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001991 }
1992 else
1993 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1994 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001995 err_code |= ERR_FATAL;
1996 goto out;
1997 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001998
Willy Tarreau4348fad2012-09-20 16:48:07 +02001999 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002000 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 }
2003
2004 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002005 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002006 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002007
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002010 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002011 curproxy->no_options = defproxy.no_options;
2012 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002013 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002014 curproxy->except_net = defproxy.except_net;
2015 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002016 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002017 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002019 if (defproxy.fwdfor_hdr_len) {
2020 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2021 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2022 }
2023
Willy Tarreaub86db342009-11-30 11:50:16 +01002024 if (defproxy.orgto_hdr_len) {
2025 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2026 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2027 }
2028
Mark Lamourinec2247f02012-01-04 13:02:01 -05002029 if (defproxy.server_id_hdr_len) {
2030 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2031 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2032 }
2033
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034 if (curproxy->cap & PR_CAP_FE) {
2035 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002036 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002037 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038
2039 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002040 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2041 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042
2043 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002047 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048 curproxy->fullconn = defproxy.fullconn;
2049 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002050 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002052 if (defproxy.check_req) {
2053 curproxy->check_req = calloc(1, defproxy.check_len);
2054 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2055 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002058 if (defproxy.expect_str) {
2059 curproxy->expect_str = strdup(defproxy.expect_str);
2060 if (defproxy.expect_regex) {
2061 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002062 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2063 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002064 }
2065 }
2066
Willy Tarreau67402132012-05-31 20:40:20 +02002067 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (defproxy.cookie_name)
2069 curproxy->cookie_name = strdup(defproxy.cookie_name);
2070 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002071 if (defproxy.cookie_domain)
2072 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002073
Willy Tarreau31936852010-10-06 16:59:56 +02002074 if (defproxy.cookie_maxidle)
2075 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2076
2077 if (defproxy.cookie_maxlife)
2078 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2079
Emeric Brun647caf12009-06-30 17:57:00 +02002080 if (defproxy.rdp_cookie_name)
2081 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2082 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2083
Willy Tarreau01732802007-11-01 22:48:15 +01002084 if (defproxy.url_param_name)
2085 curproxy->url_param_name = strdup(defproxy.url_param_name);
2086 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002087
Benoitaffb4812009-03-25 13:02:10 +01002088 if (defproxy.hh_name)
2089 curproxy->hh_name = strdup(defproxy.hh_name);
2090 curproxy->hh_len = defproxy.hh_len;
2091 curproxy->hh_match_domain = defproxy.hh_match_domain;
2092
Willy Tarreauef9a3602012-12-08 22:29:20 +01002093 if (defproxy.conn_src.iface_name)
2094 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2095 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002096 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002097#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002098 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002099#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002102 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002103 if (defproxy.capture_name)
2104 curproxy->capture_name = strdup(defproxy.capture_name);
2105 curproxy->capture_namelen = defproxy.capture_namelen;
2106 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002110 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002111 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002112 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002113 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002114 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 curproxy->mon_net = defproxy.mon_net;
2116 curproxy->mon_mask = defproxy.mon_mask;
2117 if (defproxy.monitor_uri)
2118 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2119 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002120 if (defproxy.defbe.name)
2121 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002122
2123 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002124 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2125 if (curproxy->conf.logformat_string &&
2126 curproxy->conf.logformat_string != default_http_log_format &&
2127 curproxy->conf.logformat_string != default_tcp_log_format &&
2128 curproxy->conf.logformat_string != clf_http_log_format)
2129 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2130
2131 if (defproxy.conf.lfs_file) {
2132 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2133 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2134 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002135 }
2136
2137 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002138 curproxy->timeout.connect = defproxy.timeout.connect;
2139 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002140 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002141 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002142 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002143 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002144 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002145 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002146 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002147 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002148 }
2149
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002151 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002152
2153 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002154 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002155 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002156 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002157 LIST_INIT(&node->list);
2158 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2159 }
2160
Willy Tarreau62a61232013-04-12 18:13:46 +02002161 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2162 if (curproxy->conf.uniqueid_format_string)
2163 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2164
2165 if (defproxy.conf.uif_file) {
2166 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2167 curproxy->conf.uif_line = defproxy.conf.uif_line;
2168 }
William Lallemanda73203e2012-03-12 12:48:57 +01002169
2170 /* copy default header unique id */
2171 if (defproxy.header_unique_id)
2172 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2173
William Lallemand82fe75c2012-10-23 10:25:10 +02002174 /* default compression options */
2175 if (defproxy.comp != NULL) {
2176 curproxy->comp = calloc(1, sizeof(struct comp));
2177 curproxy->comp->algos = defproxy.comp->algos;
2178 curproxy->comp->types = defproxy.comp->types;
2179 }
2180
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002182 curproxy->conf.used_listener_id = EB_ROOT;
2183 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002184
Willy Tarreau93893792009-07-23 13:19:11 +02002185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 }
2187 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2188 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002189 /* FIXME-20070101: we should do this too at the end of the
2190 * config parsing to free all default values.
2191 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002192 free(defproxy.check_req);
2193 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002194 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002195 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002196 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002197 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002198 free(defproxy.capture_name);
2199 free(defproxy.monitor_uri);
2200 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002201 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002202 free(defproxy.fwdfor_hdr_name);
2203 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002204 free(defproxy.orgto_hdr_name);
2205 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002206 free(defproxy.server_id_hdr_name);
2207 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002208 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002209 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002210 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002211 free(defproxy.expect_regex);
2212 defproxy.expect_regex = NULL;
2213 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002214
Willy Tarreau62a61232013-04-12 18:13:46 +02002215 if (defproxy.conf.logformat_string != default_http_log_format &&
2216 defproxy.conf.logformat_string != default_tcp_log_format &&
2217 defproxy.conf.logformat_string != clf_http_log_format)
2218 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002219
Willy Tarreau62a61232013-04-12 18:13:46 +02002220 free(defproxy.conf.uniqueid_format_string);
2221 free(defproxy.conf.lfs_file);
2222 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002223
Willy Tarreaua534fea2008-08-03 12:19:50 +02002224 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002225 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002226
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 /* we cannot free uri_auth because it might already be used */
2228 init_default_instance();
2229 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002230 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2231 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002232 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
2235 else if (curproxy == NULL) {
2236 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002240
2241 /* update the current file and line being parsed */
2242 curproxy->conf.args.file = curproxy->conf.file;
2243 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002244
2245 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002246 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2247 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2248 if (err_code & ERR_FATAL)
2249 goto out;
2250 }
2251 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002252 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002253 int cur_arg;
2254
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 if (curproxy == &defproxy) {
2256 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002260 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262
Willy Tarreau24709282013-03-10 21:32:12 +01002263 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002264 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002269
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002270 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002271
2272 /* use default settings for unix sockets */
2273 bind_conf->ux.uid = global.unix_bind.ux.uid;
2274 bind_conf->ux.gid = global.unix_bind.ux.gid;
2275 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002276
2277 /* NOTE: the following line might create several listeners if there
2278 * are comma-separated IPs or port ranges. So all further processing
2279 * will have to be applied to all listeners created after last_listen.
2280 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002281 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2282 if (errmsg && *errmsg) {
2283 indent_msg(&errmsg, 2);
2284 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002285 }
2286 else
2287 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2288 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
2291 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002292
Willy Tarreau4348fad2012-09-20 16:48:07 +02002293 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2294 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002295 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002296 }
2297
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002298 cur_arg = 2;
2299 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002300 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002301 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002302 char *err;
2303
Willy Tarreau26982662012-09-12 23:17:10 +02002304 kw = bind_find_kw(args[cur_arg]);
2305 if (kw) {
2306 char *err = NULL;
2307 int code;
2308
2309 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002310 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2311 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002312 cur_arg += 1 + kw->skip ;
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316
Willy Tarreau4348fad2012-09-20 16:48:07 +02002317 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002318 err_code |= code;
2319
2320 if (code) {
2321 if (err && *err) {
2322 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002323 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002324 }
2325 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002326 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2327 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002328 if (code & ERR_FATAL) {
2329 free(err);
2330 cur_arg += 1 + kw->skip;
2331 goto out;
2332 }
2333 }
2334 free(err);
2335 cur_arg += 1 + kw->skip;
2336 continue;
2337 }
2338
Willy Tarreau8638f482012-09-18 18:01:17 +02002339 err = NULL;
2340 if (!bind_dumped) {
2341 bind_dump_kws(&err);
2342 indent_msg(&err, 4);
2343 bind_dumped = 1;
2344 }
2345
2346 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2347 file, linenum, args[0], args[1], args[cur_arg],
2348 err ? " Registered keywords :" : "", err ? err : "");
2349 free(err);
2350
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002353 }
Willy Tarreau93893792009-07-23 13:19:11 +02002354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 }
2356 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002357 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
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 Tarreaubaaee002006-06-26 02:48:02 +02002366 /* flush useless bits */
2367 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002370 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002373
Willy Tarreau1c47f852006-07-09 08:22:27 +02002374 if (!*args[1]) {
2375 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2376 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002379 }
2380
Willy Tarreaua534fea2008-08-03 12:19:50 +02002381 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002382 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002383 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002384 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002385 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2386
Willy Tarreau93893792009-07-23 13:19:11 +02002387 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2390 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2391 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2392 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2393 else {
2394 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 }
2398 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002399 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002400 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002401
2402 if (curproxy == &defproxy) {
2403 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2404 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002407 }
2408
2409 if (!*args[1]) {
2410 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2411 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002414 }
2415
2416 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002417 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002418
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002419 if (curproxy->uuid <= 0) {
2420 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002421 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002424 }
2425
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002426 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2427 if (node) {
2428 struct proxy *target = container_of(node, struct proxy, conf.id);
2429 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2430 file, linenum, proxy_type_str(curproxy), curproxy->id,
2431 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002436 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002437 else if (!strcmp(args[0], "description")) {
2438 int i, len=0;
2439 char *d;
2440
Cyril Bonté99ed3272010-01-24 23:29:44 +01002441 if (curproxy == &defproxy) {
2442 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2443 file, linenum, args[0]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
2447
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002448 if (!*args[1]) {
2449 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2450 file, linenum, args[0]);
2451 return -1;
2452 }
2453
Willy Tarreau348acfe2014-04-14 15:00:39 +02002454 for (i = 1; *args[i]; i++)
2455 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002456
2457 d = (char *)calloc(1, len);
2458 curproxy->desc = d;
2459
Willy Tarreau348acfe2014-04-14 15:00:39 +02002460 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2461 for (i = 2; *args[i]; i++)
2462 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002463
2464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2466 curproxy->state = PR_STSTOPPED;
2467 }
2468 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2469 curproxy->state = PR_STNEW;
2470 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002471 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2472 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002473 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002474
2475 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002476 unsigned int low, high;
2477
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002478 if (strcmp(args[cur_arg], "all") == 0) {
2479 set = 0;
2480 break;
2481 }
2482 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002483 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002484 }
2485 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002486 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002487 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002488 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002489 char *dash = strchr(args[cur_arg], '-');
2490
2491 low = high = str2uic(args[cur_arg]);
2492 if (dash)
2493 high = str2uic(dash + 1);
2494
2495 if (high < low) {
2496 unsigned int swap = low;
2497 low = high;
2498 high = swap;
2499 }
2500
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002501 if (low < 1 || high > LONGBITS) {
2502 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2503 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002506 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002507 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002508 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002509 }
2510 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002511 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2512 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002515 }
2516 cur_arg++;
2517 }
2518 curproxy->bind_proc = set;
2519 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002520 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002521 if (curproxy == &defproxy) {
2522 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002525 }
2526
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002527 err = invalid_char(args[1]);
2528 if (err) {
2529 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2530 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002532 }
2533
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002534 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002535 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2536 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002539 }
2540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2542 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002546
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 if (*(args[1]) == 0) {
2548 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002553
Willy Tarreau67402132012-05-31 20:40:20 +02002554 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002555 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002556 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002557 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 curproxy->cookie_name = strdup(args[1]);
2559 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002560
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 cur_arg = 2;
2562 while (*(args[cur_arg])) {
2563 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002564 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
2566 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002567 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 }
2569 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002570 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002573 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002576 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002578 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002579 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002582 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002584 else if (!strcmp(args[cur_arg], "httponly")) {
2585 curproxy->ck_opts |= PR_CK_HTTPONLY;
2586 }
2587 else if (!strcmp(args[cur_arg], "secure")) {
2588 curproxy->ck_opts |= PR_CK_SECURE;
2589 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002590 else if (!strcmp(args[cur_arg], "domain")) {
2591 if (!*args[cur_arg + 1]) {
2592 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2593 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002596 }
2597
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002598 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002599 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002600 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2601 " dots nor does not start with a dot."
2602 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002603 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002604 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002605 }
2606
2607 err = invalid_domainchar(args[cur_arg + 1]);
2608 if (err) {
2609 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2610 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002613 }
2614
Willy Tarreau68a897b2009-12-03 23:28:34 +01002615 if (!curproxy->cookie_domain) {
2616 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2617 } else {
2618 /* one domain was already specified, add another one by
2619 * building the string which will be returned along with
2620 * the cookie.
2621 */
2622 char *new_ptr;
2623 int new_len = strlen(curproxy->cookie_domain) +
2624 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2625 new_ptr = malloc(new_len);
2626 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2627 free(curproxy->cookie_domain);
2628 curproxy->cookie_domain = new_ptr;
2629 }
Willy Tarreau31936852010-10-06 16:59:56 +02002630 cur_arg++;
2631 }
2632 else if (!strcmp(args[cur_arg], "maxidle")) {
2633 unsigned int maxidle;
2634 const char *res;
2635
2636 if (!*args[cur_arg + 1]) {
2637 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2638 file, linenum, args[cur_arg]);
2639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
2641 }
2642
2643 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2644 if (res) {
2645 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2646 file, linenum, *res, args[cur_arg]);
2647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
2649 }
2650 curproxy->cookie_maxidle = maxidle;
2651 cur_arg++;
2652 }
2653 else if (!strcmp(args[cur_arg], "maxlife")) {
2654 unsigned int maxlife;
2655 const char *res;
2656
2657 if (!*args[cur_arg + 1]) {
2658 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2659 file, linenum, args[cur_arg]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663
2664 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2665 if (res) {
2666 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2667 file, linenum, *res, args[cur_arg]);
2668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002672 cur_arg++;
2673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002675 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 +02002676 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 }
2680 cur_arg++;
2681 }
Willy Tarreau67402132012-05-31 20:40:20 +02002682 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2684 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 }
2687
Willy Tarreau67402132012-05-31 20:40:20 +02002688 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2690 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002691 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002693
Willy Tarreau67402132012-05-31 20:40:20 +02002694 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002695 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2696 file, linenum);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002700 else if (!strcmp(args[0], "persist")) { /* persist */
2701 if (*(args[1]) == 0) {
2702 Alert("parsing [%s:%d] : missing persist method.\n",
2703 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002706 }
2707
2708 if (!strncmp(args[1], "rdp-cookie", 10)) {
2709 curproxy->options2 |= PR_O2_RDPC_PRST;
2710
Emeric Brunb982a3d2010-01-04 15:45:53 +01002711 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002712 const char *beg, *end;
2713
2714 beg = args[1] + 11;
2715 end = strchr(beg, ')');
2716
2717 if (!end || end == beg) {
2718 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2719 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002722 }
2723
2724 free(curproxy->rdp_cookie_name);
2725 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2726 curproxy->rdp_cookie_len = end-beg;
2727 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002728 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002729 free(curproxy->rdp_cookie_name);
2730 curproxy->rdp_cookie_name = strdup("msts");
2731 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2732 }
2733 else { /* syntax */
2734 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2735 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002738 }
2739 }
2740 else {
2741 Alert("parsing [%s:%d] : unknown persist method.\n",
2742 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002745 }
2746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002748 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002750 if (curproxy == &defproxy) {
2751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
Willy Tarreau977b8e42006-12-29 14:19:17 +01002756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002758
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002760 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 }
2765 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002766 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 curproxy->appsession_name = strdup(args[1]);
2768 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2769 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002770 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2771 if (err) {
2772 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2773 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002776 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002777 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002778
Willy Tarreau51041c72007-09-09 21:56:53 +02002779 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2780 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_ALERT | ERR_ABORT;
2782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002784
2785 cur_arg = 6;
2786 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002787 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2788 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002789 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002790 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002791 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002792 } else if (!strcmp(args[cur_arg], "prefix")) {
2793 curproxy->options2 |= PR_O2_AS_PFX;
2794 } else if (!strcmp(args[cur_arg], "mode")) {
2795 if (!*args[cur_arg + 1]) {
2796 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2797 file, linenum, args[0], args[cur_arg]);
2798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
2801
2802 cur_arg++;
2803 if (!strcmp(args[cur_arg], "query-string")) {
2804 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2805 curproxy->options2 |= PR_O2_AS_M_QS;
2806 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2807 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2808 curproxy->options2 |= PR_O2_AS_M_PP;
2809 } else {
2810 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
2813 }
2814 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002815 cur_arg++;
2816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817 } /* Url App Session */
2818 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002819 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002821
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002823 if (curproxy == &defproxy) {
2824 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
2827 }
2828
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 if (*(args[4]) == 0) {
2830 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2831 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002835 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 curproxy->capture_name = strdup(args[2]);
2837 curproxy->capture_namelen = strlen(curproxy->capture_name);
2838 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 curproxy->to_log |= LW_COOKIE;
2840 }
2841 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2842 struct cap_hdr *hdr;
2843
2844 if (curproxy == &defproxy) {
2845 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 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848 }
2849
2850 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2851 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2852 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 }
2856
2857 hdr = calloc(sizeof(struct cap_hdr), 1);
2858 hdr->next = curproxy->req_cap;
2859 hdr->name = strdup(args[3]);
2860 hdr->namelen = strlen(args[3]);
2861 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002862 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 hdr->index = curproxy->nb_req_cap++;
2864 curproxy->req_cap = hdr;
2865 curproxy->to_log |= LW_REQHDR;
2866 }
2867 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2868 struct cap_hdr *hdr;
2869
2870 if (curproxy == &defproxy) {
2871 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 +02002872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 }
2875
2876 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2877 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2878 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 }
2882 hdr = calloc(sizeof(struct cap_hdr), 1);
2883 hdr->next = curproxy->rsp_cap;
2884 hdr->name = strdup(args[3]);
2885 hdr->namelen = strlen(args[3]);
2886 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002887 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 hdr->index = curproxy->nb_rsp_cap++;
2889 curproxy->rsp_cap = hdr;
2890 curproxy->to_log |= LW_RSPHDR;
2891 }
2892 else {
2893 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
2898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 if (*(args[1]) == 0) {
2904 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2905 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }
2909 curproxy->conn_retries = atol(args[1]);
2910 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002911 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002912 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002913
2914 if (curproxy == &defproxy) {
2915 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919
Willy Tarreau20b0de52012-12-24 15:45:22 +01002920 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2921 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2922 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2923 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002924 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002925 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2926 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 +01002927 file, linenum, args[0]);
2928 err_code |= ERR_WARN;
2929 }
2930
Willy Tarreauff011f22011-01-06 17:51:27 +01002931 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002932
Willy Tarreauff011f22011-01-06 17:51:27 +01002933 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002934 err_code |= ERR_ALERT | ERR_ABORT;
2935 goto out;
2936 }
2937
Willy Tarreau5002f572014-04-23 01:32:02 +02002938 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002939 err_code |= warnif_cond_conflicts(rule->cond,
2940 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2941 file, linenum);
2942
Willy Tarreauff011f22011-01-06 17:51:27 +01002943 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002944 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002945 else if (!strcmp(args[0], "http-response")) { /* response access control */
2946 struct http_res_rule *rule;
2947
2948 if (curproxy == &defproxy) {
2949 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953
2954 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2955 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2956 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2957 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2958 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2959 file, linenum, args[0]);
2960 err_code |= ERR_WARN;
2961 }
2962
2963 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2964
2965 if (!rule) {
2966 err_code |= ERR_ALERT | ERR_ABORT;
2967 goto out;
2968 }
2969
2970 err_code |= warnif_cond_conflicts(rule->cond,
2971 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2972 file, linenum);
2973
2974 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2975 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002976 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2977 /* set the header name and length into the proxy structure */
2978 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2979 err_code |= ERR_WARN;
2980
2981 if (!*args[1]) {
2982 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2983 file, linenum, args[0]);
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
2988 /* set the desired header name */
2989 free(curproxy->server_id_hdr_name);
2990 curproxy->server_id_hdr_name = strdup(args[1]);
2991 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2992 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002993 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002994 struct http_req_rule *rule;
2995
Willy Tarreaub099aca2008-10-12 17:26:37 +02002996 if (curproxy == &defproxy) {
2997 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003000 }
3001
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003002 /* emulate "block" using "http-request block". Since these rules are supposed to
3003 * be processed before all http-request rules, we put them into their own list
3004 * and will insert them at the end.
3005 */
3006 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3007 if (!rule) {
3008 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003009 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003010 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003011 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3012 err_code |= warnif_cond_conflicts(rule->cond,
3013 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3014 file, linenum);
3015 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003016
3017 if (!already_warned(WARN_BLOCK_DEPRECATED))
3018 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]);
3019
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003020 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003021 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003022 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003023
Cyril Bonté99ed3272010-01-24 23:29:44 +01003024 if (curproxy == &defproxy) {
3025 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003030 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003031 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3032 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003035 }
3036
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003037 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003038 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003039 err_code |= warnif_cond_conflicts(rule->cond,
3040 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3041 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003042 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003043 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003044 struct switching_rule *rule;
3045
Willy Tarreaub099aca2008-10-12 17:26:37 +02003046 if (curproxy == &defproxy) {
3047 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003050 }
3051
Willy Tarreau55ea7572007-06-17 19:56:27 +02003052 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003054
3055 if (*(args[1]) == 0) {
3056 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003059 }
3060
Willy Tarreauf51658d2014-04-23 01:21:56 +02003061 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3062 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3063 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3064 file, linenum, errmsg);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003068
Willy Tarreauf51658d2014-04-23 01:21:56 +02003069 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003070 }
3071
3072 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3073 rule->cond = cond;
3074 rule->be.name = strdup(args[1]);
3075 LIST_INIT(&rule->list);
3076 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3077 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003078 else if (strcmp(args[0], "use-server") == 0) {
3079 struct server_rule *rule;
3080
3081 if (curproxy == &defproxy) {
3082 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086
3087 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3088 err_code |= ERR_WARN;
3089
3090 if (*(args[1]) == 0) {
3091 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
3094 }
3095
3096 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3097 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3098 file, linenum, args[0]);
3099 err_code |= ERR_ALERT | ERR_FATAL;
3100 goto out;
3101 }
3102
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003103 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3104 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3105 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
3108 }
3109
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003110 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003111
3112 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3113 rule->cond = cond;
3114 rule->srv.name = strdup(args[1]);
3115 LIST_INIT(&rule->list);
3116 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3117 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3118 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003119 else if ((!strcmp(args[0], "force-persist")) ||
3120 (!strcmp(args[0], "ignore-persist"))) {
3121 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003122
3123 if (curproxy == &defproxy) {
3124 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128
3129 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3130 err_code |= ERR_WARN;
3131
Willy Tarreauef6494c2010-01-28 17:12:36 +01003132 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003133 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3134 file, linenum, args[0]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003139 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3140 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3141 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003146 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3147 * where force-persist is applied.
3148 */
3149 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003150
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003151 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003152 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003153 if (!strcmp(args[0], "force-persist")) {
3154 rule->type = PERSIST_TYPE_FORCE;
3155 } else {
3156 rule->type = PERSIST_TYPE_IGNORE;
3157 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003158 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003159 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003160 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003161 else if (!strcmp(args[0], "stick-table")) {
3162 int myidx = 1;
3163
Emeric Brun32da3c42010-09-23 18:39:19 +02003164 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003165 curproxy->table.type = (unsigned int)-1;
3166 while (*args[myidx]) {
3167 const char *err;
3168
3169 if (strcmp(args[myidx], "size") == 0) {
3170 myidx++;
3171 if (!*(args[myidx])) {
3172 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3173 file, linenum, args[myidx-1]);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3178 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3179 file, linenum, *err, args[myidx-1]);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003183 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003184 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003185 else if (strcmp(args[myidx], "peers") == 0) {
3186 myidx++;
Godbach50523162013-12-11 19:48:57 +08003187 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003188 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3189 file, linenum, args[myidx-1]);
3190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Godbach50523162013-12-11 19:48:57 +08003192 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003193 curproxy->table.peers.name = strdup(args[myidx++]);
3194 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003195 else if (strcmp(args[myidx], "expire") == 0) {
3196 myidx++;
3197 if (!*(args[myidx])) {
3198 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3199 file, linenum, args[myidx-1]);
3200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
3202 }
3203 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3204 if (err) {
3205 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3206 file, linenum, *err, args[myidx-1]);
3207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
3209 }
3210 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003211 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003212 }
3213 else if (strcmp(args[myidx], "nopurge") == 0) {
3214 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003215 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003216 }
3217 else if (strcmp(args[myidx], "type") == 0) {
3218 myidx++;
3219 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3220 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3221 file, linenum, args[myidx]);
3222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003225 /* myidx already points to next arg */
3226 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003227 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003228 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003229 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003230
3231 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003232 nw = args[myidx];
3233 while (*nw) {
3234 /* the "store" keyword supports a comma-separated list */
3235 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003236 sa = NULL; /* store arg */
3237 while (*nw && *nw != ',') {
3238 if (*nw == '(') {
3239 *nw = 0;
3240 sa = ++nw;
3241 while (*nw != ')') {
3242 if (!*nw) {
3243 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3244 file, linenum, args[0], cw);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248 nw++;
3249 }
3250 *nw = '\0';
3251 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003252 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003253 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003254 if (*nw)
3255 *nw++ = '\0';
3256 type = stktable_get_data_type(cw);
3257 if (type < 0) {
3258 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3259 file, linenum, args[0], cw);
3260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
3262 }
Willy Tarreauac782882010-06-20 10:41:54 +02003263
3264 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3265 switch (err) {
3266 case PE_NONE: break;
3267 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003268 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3269 file, linenum, args[0], cw);
3270 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003271 break;
3272
3273 case PE_ARG_MISSING:
3274 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3275 file, linenum, args[0], cw);
3276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278
3279 case PE_ARG_NOT_USED:
3280 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3281 file, linenum, args[0], cw);
3282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
3284
3285 default:
3286 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3287 file, linenum, args[0], cw);
3288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003290 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003291 }
3292 myidx++;
3293 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003294 else {
3295 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3296 file, linenum, args[myidx]);
3297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003299 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003300 }
3301
3302 if (!curproxy->table.size) {
3303 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3304 file, linenum);
3305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
3307 }
3308
3309 if (curproxy->table.type == (unsigned int)-1) {
3310 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3311 file, linenum);
3312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
3314 }
3315 }
3316 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003317 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003318 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003319 int myidx = 0;
3320 const char *name = NULL;
3321 int flags;
3322
3323 if (curproxy == &defproxy) {
3324 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
3329 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3330 err_code |= ERR_WARN;
3331 goto out;
3332 }
3333
3334 myidx++;
3335 if ((strcmp(args[myidx], "store") == 0) ||
3336 (strcmp(args[myidx], "store-request") == 0)) {
3337 myidx++;
3338 flags = STK_IS_STORE;
3339 }
3340 else if (strcmp(args[myidx], "store-response") == 0) {
3341 myidx++;
3342 flags = STK_IS_STORE | STK_ON_RSP;
3343 }
3344 else if (strcmp(args[myidx], "match") == 0) {
3345 myidx++;
3346 flags = STK_IS_MATCH;
3347 }
3348 else if (strcmp(args[myidx], "on") == 0) {
3349 myidx++;
3350 flags = STK_IS_MATCH | STK_IS_STORE;
3351 }
3352 else {
3353 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
3356 }
3357
3358 if (*(args[myidx]) == 0) {
3359 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003364 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003365 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003366 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003367 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371
3372 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003373 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3374 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\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 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003381 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3382 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3383 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003384 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003385 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003386 goto out;
3387 }
3388 }
3389
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003390 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003391 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003392
Emeric Brunb982a3d2010-01-04 15:45:53 +01003393 if (strcmp(args[myidx], "table") == 0) {
3394 myidx++;
3395 name = args[myidx++];
3396 }
3397
Willy Tarreauef6494c2010-01-28 17:12:36 +01003398 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003399 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3400 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3401 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003402 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003403 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003404 goto out;
3405 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003406 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003407 else if (*(args[myidx])) {
3408 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3409 file, linenum, args[0], args[myidx]);
3410 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003411 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003412 goto out;
3413 }
Emeric Brun97679e72010-09-23 17:56:44 +02003414 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003415 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003416 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003417 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003418
Emeric Brunb982a3d2010-01-04 15:45:53 +01003419 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3420 rule->cond = cond;
3421 rule->expr = expr;
3422 rule->flags = flags;
3423 rule->table.name = name ? strdup(name) : NULL;
3424 LIST_INIT(&rule->list);
3425 if (flags & STK_ON_RSP)
3426 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3427 else
3428 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 else if (!strcmp(args[0], "stats")) {
3431 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3432 curproxy->uri_auth = NULL; /* we must detach from the default config */
3433
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003434 if (!*args[1]) {
3435 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003436 } else if (!strcmp(args[1], "admin")) {
3437 struct stats_admin_rule *rule;
3438
3439 if (curproxy == &defproxy) {
3440 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444
3445 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3446 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3447 err_code |= ERR_ALERT | ERR_ABORT;
3448 goto out;
3449 }
3450
3451 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3452 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3453 file, linenum, args[0], args[1]);
3454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
3456 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003457 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3458 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3459 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003464 err_code |= warnif_cond_conflicts(cond,
3465 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3466 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003467
3468 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3469 rule->cond = cond;
3470 LIST_INIT(&rule->list);
3471 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472 } else if (!strcmp(args[1], "uri")) {
3473 if (*(args[2]) == 0) {
3474 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003477 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3478 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003479 err_code |= ERR_ALERT | ERR_ABORT;
3480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 }
3482 } else if (!strcmp(args[1], "realm")) {
3483 if (*(args[2]) == 0) {
3484 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3488 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_ABORT;
3490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003492 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003493 unsigned interval;
3494
3495 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3496 if (err) {
3497 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3498 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003501 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3502 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_ABORT;
3504 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003505 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003506 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003507 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003508
3509 if (curproxy == &defproxy) {
3510 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514
3515 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3516 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3517 err_code |= ERR_ALERT | ERR_ABORT;
3518 goto out;
3519 }
3520
Willy Tarreauff011f22011-01-06 17:51:27 +01003521 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3522 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003523 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3524 file, linenum, args[0]);
3525 err_code |= ERR_WARN;
3526 }
3527
Willy Tarreauff011f22011-01-06 17:51:27 +01003528 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003529
Willy Tarreauff011f22011-01-06 17:51:27 +01003530 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003531 err_code |= ERR_ALERT | ERR_ABORT;
3532 goto out;
3533 }
3534
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003535 err_code |= warnif_cond_conflicts(rule->cond,
3536 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3537 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003538 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003539
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 } else if (!strcmp(args[1], "auth")) {
3541 if (*(args[2]) == 0) {
3542 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3546 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_ABORT;
3548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 }
3550 } else if (!strcmp(args[1], "scope")) {
3551 if (*(args[2]) == 0) {
3552 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3556 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_ABORT;
3558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
3560 } else if (!strcmp(args[1], "enable")) {
3561 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3562 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_ABORT;
3564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003566 } else if (!strcmp(args[1], "hide-version")) {
3567 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_ABORT;
3570 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003571 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003572 } else if (!strcmp(args[1], "show-legends")) {
3573 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3574 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3575 err_code |= ERR_ALERT | ERR_ABORT;
3576 goto out;
3577 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003578 } else if (!strcmp(args[1], "show-node")) {
3579
3580 if (*args[2]) {
3581 int i;
3582 char c;
3583
3584 for (i=0; args[2][i]; i++) {
3585 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003586 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3587 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003588 break;
3589 }
3590
3591 if (!i || args[2][i]) {
3592 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3593 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3594 file, linenum, args[0], args[1]);
3595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
3597 }
3598 }
3599
3600 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3601 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3602 err_code |= ERR_ALERT | ERR_ABORT;
3603 goto out;
3604 }
3605 } else if (!strcmp(args[1], "show-desc")) {
3606 char *desc = NULL;
3607
3608 if (*args[2]) {
3609 int i, len=0;
3610 char *d;
3611
Willy Tarreau348acfe2014-04-14 15:00:39 +02003612 for (i = 2; *args[i]; i++)
3613 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003614
3615 desc = d = (char *)calloc(1, len);
3616
Willy Tarreau348acfe2014-04-14 15:00:39 +02003617 d += snprintf(d, desc + len - d, "%s", args[2]);
3618 for (i = 3; *args[i]; i++)
3619 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003620 }
3621
3622 if (!*args[2] && !global.desc)
3623 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3624 file, linenum, args[1]);
3625 else {
3626 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3627 free(desc);
3628 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3629 err_code |= ERR_ALERT | ERR_ABORT;
3630 goto out;
3631 }
3632 free(desc);
3633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003635stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003636 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 +01003637 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 }
3641 }
3642 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003643 int optnum;
3644
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003645 if (*(args[1]) == '\0') {
3646 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003651
3652 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3653 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003654 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3655 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3656 file, linenum, cfg_opts[optnum].name);
3657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
3659 }
Willy Tarreau93893792009-07-23 13:19:11 +02003660 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3661 err_code |= ERR_WARN;
3662 goto out;
3663 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003664
Willy Tarreau3842f002009-06-14 11:39:52 +02003665 curproxy->no_options &= ~cfg_opts[optnum].val;
3666 curproxy->options &= ~cfg_opts[optnum].val;
3667
3668 switch (kwm) {
3669 case KWM_STD:
3670 curproxy->options |= cfg_opts[optnum].val;
3671 break;
3672 case KWM_NO:
3673 curproxy->no_options |= cfg_opts[optnum].val;
3674 break;
3675 case KWM_DEF: /* already cleared */
3676 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003677 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003678
Willy Tarreau93893792009-07-23 13:19:11 +02003679 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003680 }
3681 }
3682
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003683 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3684 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003685 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3686 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3687 file, linenum, cfg_opts2[optnum].name);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
Willy Tarreau93893792009-07-23 13:19:11 +02003691 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3692 err_code |= ERR_WARN;
3693 goto out;
3694 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003695
Willy Tarreau3842f002009-06-14 11:39:52 +02003696 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3697 curproxy->options2 &= ~cfg_opts2[optnum].val;
3698
3699 switch (kwm) {
3700 case KWM_STD:
3701 curproxy->options2 |= cfg_opts2[optnum].val;
3702 break;
3703 case KWM_NO:
3704 curproxy->no_options2 |= cfg_opts2[optnum].val;
3705 break;
3706 case KWM_DEF: /* already cleared */
3707 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003708 }
Willy Tarreau93893792009-07-23 13:19:11 +02003709 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003710 }
3711 }
3712
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003713 /* HTTP options override each other. They can be cancelled using
3714 * "no option xxx" which only switches to default mode if the mode
3715 * was this one (useful for cancelling options set in defaults
3716 * sections).
3717 */
3718 if (strcmp(args[1], "httpclose") == 0) {
3719 if (kwm == KWM_STD) {
3720 curproxy->options &= ~PR_O_HTTP_MODE;
3721 curproxy->options |= PR_O_HTTP_PCL;
3722 goto out;
3723 }
3724 else if (kwm == KWM_NO) {
3725 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3726 curproxy->options &= ~PR_O_HTTP_MODE;
3727 goto out;
3728 }
3729 }
3730 else if (strcmp(args[1], "forceclose") == 0) {
3731 if (kwm == KWM_STD) {
3732 curproxy->options &= ~PR_O_HTTP_MODE;
3733 curproxy->options |= PR_O_HTTP_FCL;
3734 goto out;
3735 }
3736 else if (kwm == KWM_NO) {
3737 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3738 curproxy->options &= ~PR_O_HTTP_MODE;
3739 goto out;
3740 }
3741 }
3742 else if (strcmp(args[1], "http-server-close") == 0) {
3743 if (kwm == KWM_STD) {
3744 curproxy->options &= ~PR_O_HTTP_MODE;
3745 curproxy->options |= PR_O_HTTP_SCL;
3746 goto out;
3747 }
3748 else if (kwm == KWM_NO) {
3749 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3750 curproxy->options &= ~PR_O_HTTP_MODE;
3751 goto out;
3752 }
3753 }
3754 else if (strcmp(args[1], "http-keep-alive") == 0) {
3755 if (kwm == KWM_STD) {
3756 curproxy->options &= ~PR_O_HTTP_MODE;
3757 curproxy->options |= PR_O_HTTP_KAL;
3758 goto out;
3759 }
3760 else if (kwm == KWM_NO) {
3761 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3762 curproxy->options &= ~PR_O_HTTP_MODE;
3763 goto out;
3764 }
3765 }
3766 else if (strcmp(args[1], "http-tunnel") == 0) {
3767 if (kwm == KWM_STD) {
3768 curproxy->options &= ~PR_O_HTTP_MODE;
3769 curproxy->options |= PR_O_HTTP_TUN;
3770 goto out;
3771 }
3772 else if (kwm == KWM_NO) {
3773 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3774 curproxy->options &= ~PR_O_HTTP_MODE;
3775 goto out;
3776 }
3777 }
3778
Willy Tarreau3842f002009-06-14 11:39:52 +02003779 if (kwm != KWM_STD) {
3780 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003781 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003784 }
3785
Emeric Brun3a058f32009-06-30 18:26:00 +02003786 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003787 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003789 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003790 if (*(args[2]) != '\0') {
3791 if (!strcmp(args[2], "clf")) {
3792 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003793 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003794 } else {
3795 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003798 }
3799 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003800 if (curproxy->conf.logformat_string != default_http_log_format &&
3801 curproxy->conf.logformat_string != default_tcp_log_format &&
3802 curproxy->conf.logformat_string != clf_http_log_format)
3803 free(curproxy->conf.logformat_string);
3804 curproxy->conf.logformat_string = logformat;
3805
3806 free(curproxy->conf.lfs_file);
3807 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3808 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003809 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003810 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003812 if (curproxy->conf.logformat_string != default_http_log_format &&
3813 curproxy->conf.logformat_string != default_tcp_log_format &&
3814 curproxy->conf.logformat_string != clf_http_log_format)
3815 free(curproxy->conf.logformat_string);
3816 curproxy->conf.logformat_string = default_tcp_log_format;
3817
3818 free(curproxy->conf.lfs_file);
3819 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3820 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003821 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 else if (!strcmp(args[1], "tcpka")) {
3823 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003824 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003826
3827 if (curproxy->cap & PR_CAP_FE)
3828 curproxy->options |= PR_O_TCP_CLI_KA;
3829 if (curproxy->cap & PR_CAP_BE)
3830 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003831 }
3832 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003833 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_WARN;
3835
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003837 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003838 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003839 curproxy->options2 &= ~PR_O2_CHK_ANY;
3840 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 if (!*args[2]) { /* no argument */
3842 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3843 curproxy->check_len = strlen(DEF_CHECK_REQ);
3844 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003845 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 curproxy->check_req = (char *)malloc(reqlen);
3847 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003848 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003850 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 if (*args[4])
3852 reqlen += strlen(args[4]);
3853 else
3854 reqlen += strlen("HTTP/1.0");
3855
3856 curproxy->check_req = (char *)malloc(reqlen);
3857 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003858 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003860 }
3861 else if (!strcmp(args[1], "ssl-hello-chk")) {
3862 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003865
Willy Tarreaua534fea2008-08-03 12:19:50 +02003866 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003867 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003868 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003869 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003870 }
Willy Tarreau23677902007-05-08 23:50:35 +02003871 else if (!strcmp(args[1], "smtpchk")) {
3872 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003873 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003874 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003875 curproxy->options2 &= ~PR_O2_CHK_ANY;
3876 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003877
3878 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3879 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3880 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3881 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3882 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3883 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3884 curproxy->check_req = (char *)malloc(reqlen);
3885 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3886 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3887 } else {
3888 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3889 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3890 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3891 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3892 }
3893 }
3894 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003895 else if (!strcmp(args[1], "pgsql-check")) {
3896 /* use PostgreSQL request to check servers' health */
3897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3898 err_code |= ERR_WARN;
3899
3900 free(curproxy->check_req);
3901 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003902 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003903 curproxy->options2 |= PR_O2_PGSQL_CHK;
3904
3905 if (*(args[2])) {
3906 int cur_arg = 2;
3907
3908 while (*(args[cur_arg])) {
3909 if (strcmp(args[cur_arg], "user") == 0) {
3910 char * packet;
3911 uint32_t packet_len;
3912 uint32_t pv;
3913
3914 /* suboption header - needs additional argument for it */
3915 if (*(args[cur_arg+1]) == 0) {
3916 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3917 file, linenum, args[0], args[1], args[cur_arg]);
3918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
3920 }
3921
3922 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3923 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3924 pv = htonl(0x30000); /* protocol version 3.0 */
3925
3926 packet = (char*) calloc(1, packet_len);
3927
3928 memcpy(packet + 4, &pv, 4);
3929
3930 /* copy "user" */
3931 memcpy(packet + 8, "user", 4);
3932
3933 /* copy username */
3934 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3935
3936 free(curproxy->check_req);
3937 curproxy->check_req = packet;
3938 curproxy->check_len = packet_len;
3939
3940 packet_len = htonl(packet_len);
3941 memcpy(packet, &packet_len, 4);
3942 cur_arg += 2;
3943 } else {
3944 /* unknown suboption - catchall */
3945 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3946 file, linenum, args[0], args[1]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950 } /* end while loop */
3951 }
3952 }
3953
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003954 else if (!strcmp(args[1], "redis-check")) {
3955 /* use REDIS PING request to check servers' health */
3956 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3957 err_code |= ERR_WARN;
3958
3959 free(curproxy->check_req);
3960 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003961 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003962 curproxy->options2 |= PR_O2_REDIS_CHK;
3963
3964 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3965 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3966 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3967 }
3968
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003969 else if (!strcmp(args[1], "mysql-check")) {
3970 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3972 err_code |= ERR_WARN;
3973
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003974 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003975 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003976 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003977 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003978
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003979 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003980 * const char mysql40_client_auth_pkt[] = {
3981 * "\x0e\x00\x00" // packet length
3982 * "\x01" // packet number
3983 * "\x00\x00" // client capabilities
3984 * "\x00\x00\x01" // max packet
3985 * "haproxy\x00" // username (null terminated string)
3986 * "\x00" // filler (always 0x00)
3987 * "\x01\x00\x00" // packet length
3988 * "\x00" // packet number
3989 * "\x01" // COM_QUIT command
3990 * };
3991 */
3992
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003993 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3994 * const char mysql41_client_auth_pkt[] = {
3995 * "\x0e\x00\x00\" // packet length
3996 * "\x01" // packet number
3997 * "\x00\x00\x00\x00" // client capabilities
3998 * "\x00\x00\x00\x01" // max packet
3999 * "\x21" // character set (UTF-8)
4000 * char[23] // All zeroes
4001 * "haproxy\x00" // username (null terminated string)
4002 * "\x00" // filler (always 0x00)
4003 * "\x01\x00\x00" // packet length
4004 * "\x00" // packet number
4005 * "\x01" // COM_QUIT command
4006 * };
4007 */
4008
4009
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004010 if (*(args[2])) {
4011 int cur_arg = 2;
4012
4013 while (*(args[cur_arg])) {
4014 if (strcmp(args[cur_arg], "user") == 0) {
4015 char *mysqluser;
4016 int packetlen, reqlen, userlen;
4017
4018 /* suboption header - needs additional argument for it */
4019 if (*(args[cur_arg+1]) == 0) {
4020 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4021 file, linenum, args[0], args[1], args[cur_arg]);
4022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
4024 }
4025 mysqluser = args[cur_arg + 1];
4026 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004027
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004028 if (*(args[cur_arg+2])) {
4029 if (!strcmp(args[cur_arg+2], "post-41")) {
4030 packetlen = userlen + 7 + 27;
4031 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004032
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004033 free(curproxy->check_req);
4034 curproxy->check_req = (char *)calloc(1, reqlen);
4035 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004036
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004037 snprintf(curproxy->check_req, 4, "%c%c%c",
4038 ((unsigned char) packetlen & 0xff),
4039 ((unsigned char) (packetlen >> 8) & 0xff),
4040 ((unsigned char) (packetlen >> 16) & 0xff));
4041
4042 curproxy->check_req[3] = 1;
4043 curproxy->check_req[5] = 130;
4044 curproxy->check_req[11] = 1;
4045 curproxy->check_req[12] = 33;
4046 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4047 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4048 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4049 cur_arg += 3;
4050 } else {
4051 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055 } else {
4056 packetlen = userlen + 7;
4057 reqlen = packetlen + 9;
4058
4059 free(curproxy->check_req);
4060 curproxy->check_req = (char *)calloc(1, reqlen);
4061 curproxy->check_len = reqlen;
4062
4063 snprintf(curproxy->check_req, 4, "%c%c%c",
4064 ((unsigned char) packetlen & 0xff),
4065 ((unsigned char) (packetlen >> 8) & 0xff),
4066 ((unsigned char) (packetlen >> 16) & 0xff));
4067
4068 curproxy->check_req[3] = 1;
4069 curproxy->check_req[5] = 128;
4070 curproxy->check_req[8] = 1;
4071 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4072 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4073 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4074 cur_arg += 2;
4075 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004076 } else {
4077 /* unknown suboption - catchall */
4078 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4079 file, linenum, args[0], args[1]);
4080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
4082 }
4083 } /* end while loop */
4084 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004085 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004086 else if (!strcmp(args[1], "ldap-check")) {
4087 /* use LDAP request to check servers' health */
4088 free(curproxy->check_req);
4089 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004090 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004091 curproxy->options2 |= PR_O2_LDAP_CHK;
4092
4093 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4094 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4095 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4096 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004097 else if (!strcmp(args[1], "tcp-check")) {
4098 /* use raw TCPCHK send/expect to check servers' health */
4099 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4100 err_code |= ERR_WARN;
4101
4102 free(curproxy->check_req);
4103 curproxy->check_req = NULL;
4104 curproxy->options2 &= ~PR_O2_CHK_ANY;
4105 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4106 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004107 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004108 int cur_arg;
4109
4110 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4111 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004112 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004113
Willy Tarreau87cf5142011-08-19 22:57:24 +02004114 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004115
4116 free(curproxy->fwdfor_hdr_name);
4117 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4118 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4119
4120 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4121 cur_arg = 2;
4122 while (*(args[cur_arg])) {
4123 if (!strcmp(args[cur_arg], "except")) {
4124 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004125 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004126 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4127 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004130 }
4131 /* flush useless bits */
4132 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004133 cur_arg += 2;
4134 } else if (!strcmp(args[cur_arg], "header")) {
4135 /* suboption header - needs additional argument for it */
4136 if (*(args[cur_arg+1]) == 0) {
4137 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4138 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004141 }
4142 free(curproxy->fwdfor_hdr_name);
4143 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4144 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4145 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004146 } else if (!strcmp(args[cur_arg], "if-none")) {
4147 curproxy->options &= ~PR_O_FF_ALWAYS;
4148 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004149 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004150 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004151 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004152 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004155 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004156 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004157 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004158 else if (!strcmp(args[1], "originalto")) {
4159 int cur_arg;
4160
4161 /* insert x-original-to field, but not for the IP address listed as an except.
4162 * set default options (ie: bitfield, header name, etc)
4163 */
4164
4165 curproxy->options |= PR_O_ORGTO;
4166
4167 free(curproxy->orgto_hdr_name);
4168 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4169 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4170
Willy Tarreau87cf5142011-08-19 22:57:24 +02004171 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004172 cur_arg = 2;
4173 while (*(args[cur_arg])) {
4174 if (!strcmp(args[cur_arg], "except")) {
4175 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004176 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 +02004177 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4178 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004181 }
4182 /* flush useless bits */
4183 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4184 cur_arg += 2;
4185 } else if (!strcmp(args[cur_arg], "header")) {
4186 /* suboption header - needs additional argument for it */
4187 if (*(args[cur_arg+1]) == 0) {
4188 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4189 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004192 }
4193 free(curproxy->orgto_hdr_name);
4194 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4195 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4196 cur_arg += 2;
4197 } else {
4198 /* unknown suboption - catchall */
4199 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4200 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004203 }
4204 } /* end while loop */
4205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 else {
4207 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 }
Willy Tarreau93893792009-07-23 13:19:11 +02004211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004213 else if (!strcmp(args[0], "default_backend")) {
4214 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004215 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004216
4217 if (*(args[1]) == 0) {
4218 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004221 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004222 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004223 curproxy->defbe.name = strdup(args[1]);
4224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004227 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004228
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004229 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4230 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 +01004231 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 /* enable reconnections to dispatch */
4234 curproxy->options |= PR_O_REDISP;
4235 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004236 else if (!strcmp(args[0], "http-check")) {
4237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004239
4240 if (strcmp(args[1], "disable-on-404") == 0) {
4241 /* enable a graceful server shutdown on an HTTP 404 response */
4242 curproxy->options |= PR_O_DISABLE404;
4243 }
Willy Tarreauef781042010-01-27 11:53:01 +01004244 else if (strcmp(args[1], "send-state") == 0) {
4245 /* enable emission of the apparent state of a server in HTTP checks */
4246 curproxy->options2 |= PR_O2_CHK_SNDST;
4247 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004248 else if (strcmp(args[1], "expect") == 0) {
4249 const char *ptr_arg;
4250 int cur_arg;
4251
4252 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4253 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257
4258 cur_arg = 2;
4259 /* consider exclamation marks, sole or at the beginning of a word */
4260 while (*(ptr_arg = args[cur_arg])) {
4261 while (*ptr_arg == '!') {
4262 curproxy->options2 ^= PR_O2_EXP_INV;
4263 ptr_arg++;
4264 }
4265 if (*ptr_arg)
4266 break;
4267 cur_arg++;
4268 }
4269 /* now ptr_arg points to the beginning of a word past any possible
4270 * exclamation mark, and cur_arg is the argument which holds this word.
4271 */
4272 if (strcmp(ptr_arg, "status") == 0) {
4273 if (!*(args[cur_arg + 1])) {
4274 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4275 file, linenum, args[0], args[1], ptr_arg);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004280 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004281 curproxy->expect_str = strdup(args[cur_arg + 1]);
4282 }
4283 else if (strcmp(ptr_arg, "string") == 0) {
4284 if (!*(args[cur_arg + 1])) {
4285 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4286 file, linenum, args[0], args[1], ptr_arg);
4287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
4289 }
4290 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004291 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004292 curproxy->expect_str = strdup(args[cur_arg + 1]);
4293 }
4294 else if (strcmp(ptr_arg, "rstatus") == 0) {
4295 if (!*(args[cur_arg + 1])) {
4296 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4297 file, linenum, args[0], args[1], ptr_arg);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
4301 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004302 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004303 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004304 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004305 free(curproxy->expect_regex);
4306 curproxy->expect_regex = NULL;
4307 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004308 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004309 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4310 error = NULL;
4311 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4312 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4313 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4314 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 }
4319 else if (strcmp(ptr_arg, "rstring") == 0) {
4320 if (!*(args[cur_arg + 1])) {
4321 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4322 file, linenum, args[0], args[1], ptr_arg);
4323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
4325 }
4326 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004327 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004328 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004329 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004330 free(curproxy->expect_regex);
4331 curproxy->expect_regex = NULL;
4332 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004333 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004334 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4335 error = NULL;
4336 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4337 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4338 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4339 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342 }
4343 }
4344 else {
4345 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4346 file, linenum, args[0], args[1], ptr_arg);
4347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
4349 }
4350 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004351 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004352 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 +02004353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004355 }
4356 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004357 else if (!strcmp(args[0], "tcp-check")) {
4358 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4359 err_code |= ERR_WARN;
4360
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004361 if (strcmp(args[1], "connect") == 0) {
4362 const char *ptr_arg;
4363 int cur_arg;
4364 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004365
4366 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004367 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004368
Willy Tarreau5bff0592015-05-13 12:24:53 +02004369 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4370 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4371 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4372 file, linenum);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004375 }
4376
4377 cur_arg = 2;
4378 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4379 tcpcheck->action = TCPCHK_ACT_CONNECT;
4380
4381 /* parsing each parameters to fill up the rule */
4382 while (*(ptr_arg = args[cur_arg])) {
4383 /* tcp port */
4384 if (strcmp(args[cur_arg], "port") == 0) {
4385 if ( (atol(args[cur_arg + 1]) > 65535) ||
4386 (atol(args[cur_arg + 1]) < 1) ){
4387 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4388 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
4392 tcpcheck->port = atol(args[cur_arg + 1]);
4393 cur_arg += 2;
4394 }
4395 /* send proxy protocol */
4396 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4397 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4398 cur_arg++;
4399 }
4400#ifdef USE_OPENSSL
4401 else if (strcmp(args[cur_arg], "ssl") == 0) {
4402 curproxy->options |= PR_O_TCPCHK_SSL;
4403 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4404 cur_arg++;
4405 }
4406#endif /* USE_OPENSSL */
4407 else {
4408#ifdef USE_OPENSSL
4409 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4410#else /* USE_OPENSSL */
4411 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4412#endif /* USE_OPENSSL */
4413 file, linenum, args[0], args[1], args[cur_arg]);
4414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
4416 }
4417
4418 }
4419
4420 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4421 }
4422 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004423 if (! *(args[2]) ) {
4424 /* SEND string expected */
4425 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4426 file, linenum, args[0], args[1], args[2]);
4427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
4429 } else {
4430 struct tcpcheck_rule *tcpcheck;
4431
4432 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4433
4434 tcpcheck->action = TCPCHK_ACT_SEND;
4435 tcpcheck->string_len = strlen(args[2]);
4436 tcpcheck->string = strdup(args[2]);
4437 tcpcheck->expect_regex = NULL;
4438
4439 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4440 }
4441 }
4442 else if (strcmp(args[1], "send-binary") == 0) {
4443 if (! *(args[2]) ) {
4444 /* SEND binary string expected */
4445 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4446 file, linenum, args[0], args[1], args[2]);
4447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
4449 } else {
4450 struct tcpcheck_rule *tcpcheck;
4451 char *err = NULL;
4452
4453 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4454
4455 tcpcheck->action = TCPCHK_ACT_SEND;
4456 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4457 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4458 file, linenum, args[0], args[1], args[2], err);
4459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
4461 }
4462 tcpcheck->expect_regex = NULL;
4463
4464 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4465 }
4466 }
4467 else if (strcmp(args[1], "expect") == 0) {
4468 const char *ptr_arg;
4469 int cur_arg;
4470 int inverse = 0;
4471
4472 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4473 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
4476 }
4477
4478 cur_arg = 2;
4479 /* consider exclamation marks, sole or at the beginning of a word */
4480 while (*(ptr_arg = args[cur_arg])) {
4481 while (*ptr_arg == '!') {
4482 inverse = !inverse;
4483 ptr_arg++;
4484 }
4485 if (*ptr_arg)
4486 break;
4487 cur_arg++;
4488 }
4489 /* now ptr_arg points to the beginning of a word past any possible
4490 * exclamation mark, and cur_arg is the argument which holds this word.
4491 */
4492 if (strcmp(ptr_arg, "binary") == 0) {
4493 if (!*(args[cur_arg + 1])) {
4494 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4495 file, linenum, args[0], args[1], ptr_arg);
4496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
4498 }
4499 struct tcpcheck_rule *tcpcheck;
4500 char *err = NULL;
4501
4502 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4503
4504 tcpcheck->action = TCPCHK_ACT_EXPECT;
4505 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4506 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4507 file, linenum, args[0], args[1], args[2], err);
4508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
4510 }
4511 tcpcheck->expect_regex = NULL;
4512 tcpcheck->inverse = inverse;
4513
4514 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4515 }
4516 else if (strcmp(ptr_arg, "string") == 0) {
4517 if (!*(args[cur_arg + 1])) {
4518 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4519 file, linenum, args[0], args[1], ptr_arg);
4520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
4522 }
4523 struct tcpcheck_rule *tcpcheck;
4524
4525 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4526
4527 tcpcheck->action = TCPCHK_ACT_EXPECT;
4528 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4529 tcpcheck->string = strdup(args[cur_arg + 1]);
4530 tcpcheck->expect_regex = NULL;
4531 tcpcheck->inverse = inverse;
4532
4533 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4534 }
4535 else if (strcmp(ptr_arg, "rstring") == 0) {
4536 if (!*(args[cur_arg + 1])) {
4537 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4538 file, linenum, args[0], args[1], ptr_arg);
4539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
4541 }
4542 struct tcpcheck_rule *tcpcheck;
4543
4544 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4545
4546 tcpcheck->action = TCPCHK_ACT_EXPECT;
4547 tcpcheck->string_len = 0;
4548 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004549 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4550 error = NULL;
4551 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4552 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4553 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4554 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
4557 }
4558 tcpcheck->inverse = inverse;
4559
4560 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4561 }
4562 else {
4563 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4564 file, linenum, args[0], args[1], ptr_arg);
4565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
4568 }
4569 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004570 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
4573 }
4574 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004575 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004576 if (curproxy == &defproxy) {
4577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004580 }
4581
Willy Tarreaub80c2302007-11-30 20:51:32 +01004582 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004584
4585 if (strcmp(args[1], "fail") == 0) {
4586 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004587 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004588 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4589 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004592 }
4593
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004594 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4595 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4596 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004599 }
4600 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4601 }
4602 else {
4603 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004606 }
4607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608#ifdef TPROXY
4609 else if (!strcmp(args[0], "transparent")) {
4610 /* enable transparent proxy connections */
4611 curproxy->options |= PR_O_TRANSP;
4612 }
4613#endif
4614 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004615 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004617
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 if (*(args[1]) == 0) {
4619 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 }
4623 curproxy->maxconn = atol(args[1]);
4624 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004625 else if (!strcmp(args[0], "backlog")) { /* backlog */
4626 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004627 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004628
4629 if (*(args[1]) == 0) {
4630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004633 }
4634 curproxy->backlog = atol(args[1]);
4635 }
Willy Tarreau86034312006-12-29 00:10:33 +01004636 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004637 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004638 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004639
Willy Tarreau86034312006-12-29 00:10:33 +01004640 if (*(args[1]) == 0) {
4641 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004644 }
4645 curproxy->fullconn = atol(args[1]);
4646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4648 if (*(args[1]) == 0) {
4649 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004653 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4654 if (err) {
4655 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4656 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004659 }
4660 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 }
4662 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004663 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004664 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004665 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004666
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 if (curproxy == &defproxy) {
4668 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004671 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004672 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004673 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004674
Willy Tarreau902636f2013-03-10 19:44:48 +01004675 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004676 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004677 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004678 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004679 goto out;
4680 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004681
4682 proto = protocol_by_family(sk->ss_family);
4683 if (!proto || !proto->connect) {
4684 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4685 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
4688 }
4689
4690 if (port1 != port2) {
4691 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4692 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004696
4697 if (!port1) {
4698 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4699 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
4702 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004703
Willy Tarreaud5191e72010-02-09 20:50:45 +01004704 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004705 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004706 }
4707 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004708 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004709 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004710
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004711 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4712 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004717 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004718 /**
4719 * The syntax for hash-type config element is
4720 * hash-type {map-based|consistent} [[<algo>] avalanche]
4721 *
4722 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4723 */
4724 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004725
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4727 err_code |= ERR_WARN;
4728
4729 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004730 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4731 }
4732 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004733 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4734 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004735 else if (strcmp(args[1], "avalanche") == 0) {
4736 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]);
4737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004739 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004740 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004741 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
4744 }
Bhaskar98634f02013-10-29 23:30:51 -04004745
4746 /* set the hash function to use */
4747 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004748 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004749 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004750
4751 /* if consistent with no argument, then avalanche modifier is also applied */
4752 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4753 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004754 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004755 /* set the hash function */
4756 if (!strcmp(args[2], "sdbm")) {
4757 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4758 }
4759 else if (!strcmp(args[2], "djb2")) {
4760 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004761 } else if (!strcmp(args[2], "wt6")) {
4762 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004763 }
4764 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004765 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 -05004766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
4768 }
4769
4770 /* set the hash modifier */
4771 if (!strcmp(args[3], "avalanche")) {
4772 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4773 }
4774 else if (*args[3]) {
4775 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
4778 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004779 }
William Lallemanda73203e2012-03-12 12:48:57 +01004780 }
William Lallemanda73203e2012-03-12 12:48:57 +01004781 else if (strcmp(args[0], "unique-id-format") == 0) {
4782 if (!*(args[1])) {
4783 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786 }
William Lallemand3203ff42012-11-11 17:30:56 +01004787 if (*(args[2])) {
4788 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004792 free(curproxy->conf.uniqueid_format_string);
4793 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004794
Willy Tarreau62a61232013-04-12 18:13:46 +02004795 free(curproxy->conf.uif_file);
4796 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4797 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004798 }
William Lallemanda73203e2012-03-12 12:48:57 +01004799
4800 else if (strcmp(args[0], "unique-id-header") == 0) {
4801 if (!*(args[1])) {
4802 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
4805 }
4806 free(curproxy->header_unique_id);
4807 curproxy->header_unique_id = strdup(args[1]);
4808 }
4809
William Lallemand723b73a2012-02-08 16:37:49 +01004810 else if (strcmp(args[0], "log-format") == 0) {
4811 if (!*(args[1])) {
4812 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
William Lallemand3203ff42012-11-11 17:30:56 +01004816 if (*(args[2])) {
4817 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004821
Willy Tarreau62a61232013-04-12 18:13:46 +02004822 if (curproxy->conf.logformat_string != default_http_log_format &&
4823 curproxy->conf.logformat_string != default_tcp_log_format &&
4824 curproxy->conf.logformat_string != clf_http_log_format)
4825 free(curproxy->conf.logformat_string);
4826 curproxy->conf.logformat_string = strdup(args[1]);
4827
4828 free(curproxy->conf.lfs_file);
4829 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4830 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004831
4832 /* get a chance to improve log-format error reporting by
4833 * reporting the correct line-number when possible.
4834 */
4835 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4836 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4837 file, linenum, curproxy->id);
4838 err_code |= ERR_WARN;
4839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 }
William Lallemand723b73a2012-02-08 16:37:49 +01004841
William Lallemand0f99e342011-10-12 17:50:54 +02004842 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4843 /* delete previous herited or defined syslog servers */
4844 struct logsrv *back;
4845
4846 if (*(args[1]) != 0) {
4847 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
4851
William Lallemand723b73a2012-02-08 16:37:49 +01004852 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4853 LIST_DEL(&tmplogsrv->list);
4854 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004855 }
4856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004858 struct logsrv *logsrv;
4859
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004861 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004862 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004863 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004864 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004865 LIST_INIT(&node->list);
4866 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4867 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 }
4869 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004870 struct sockaddr_storage *sk;
4871 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004872 int arg = 0;
4873 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004874
4875 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004876
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004877 /* just after the address, a length may be specified */
4878 if (strcmp(args[arg+2], "len") == 0) {
4879 len = atoi(args[arg+3]);
4880 if (len < 80 || len > 65535) {
4881 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4882 file, linenum, args[arg+3]);
4883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
4885 }
4886 logsrv->maxlen = len;
4887
4888 /* skip these two args */
4889 arg += 2;
4890 }
4891 else
4892 logsrv->maxlen = MAX_SYSLOG_LEN;
4893
4894 if (logsrv->maxlen > global.max_syslog_len) {
4895 global.max_syslog_len = logsrv->maxlen;
4896 logline = realloc(logline, global.max_syslog_len + 1);
4897 }
4898
4899 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004900 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004901 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
4904
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 }
4906
William Lallemand0f99e342011-10-12 17:50:54 +02004907 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004908 if (*(args[arg+3])) {
4909 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004910 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004911 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
4914
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
4916 }
4917
William Lallemand0f99e342011-10-12 17:50:54 +02004918 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004919 if (*(args[arg+4])) {
4920 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004921 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004922 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004926 }
4927 }
4928
Willy Tarreau902636f2013-03-10 19:44:48 +01004929 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004930 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004931 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004932 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004933 goto out;
4934 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004935
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004936 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004937
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004938 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004939 if (port1 != port2) {
4940 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4941 file, linenum, args[0], args[1]);
4942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
4944 }
4945
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004946 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004947 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 }
William Lallemand0f99e342011-10-12 17:50:54 +02004949
4950 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 else {
4953 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4954 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
4958 }
4959 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004960 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004961 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004962 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004963 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004964
Willy Tarreau977b8e42006-12-29 14:19:17 +01004965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004967
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004969 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4970 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004974
4975 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004976 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4977 free(curproxy->conn_src.iface_name);
4978 curproxy->conn_src.iface_name = NULL;
4979 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004980
Willy Tarreau902636f2013-03-10 19:44:48 +01004981 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004982 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004983 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004984 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004985 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004986 goto out;
4987 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004988
4989 proto = protocol_by_family(sk->ss_family);
4990 if (!proto || !proto->connect) {
4991 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004992 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
4995 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004996
4997 if (port1 != port2) {
4998 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4999 file, linenum, args[0], args[1]);
5000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
5002 }
5003
Willy Tarreauef9a3602012-12-08 22:29:20 +01005004 curproxy->conn_src.source_addr = *sk;
5005 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005006
5007 cur_arg = 2;
5008 while (*(args[cur_arg])) {
5009 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005010#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5011#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005012 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005013 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5014 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005017 }
5018#endif
5019 if (!*args[cur_arg + 1]) {
5020 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5021 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005024 }
5025
5026 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005027 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5028 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005029 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005030 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5031 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005032 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5033 char *name, *end;
5034
5035 name = args[cur_arg+1] + 7;
5036 while (isspace(*name))
5037 name++;
5038
5039 end = name;
5040 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5041 end++;
5042
Willy Tarreauef9a3602012-12-08 22:29:20 +01005043 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5044 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5045 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5046 curproxy->conn_src.bind_hdr_len = end - name;
5047 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5048 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5049 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005050
5051 /* now look for an occurrence number */
5052 while (isspace(*end))
5053 end++;
5054 if (*end == ',') {
5055 end++;
5056 name = end;
5057 if (*end == '-')
5058 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005059 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005060 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005061 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005062 }
5063
Willy Tarreauef9a3602012-12-08 22:29:20 +01005064 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005065 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5066 " occurrences values smaller than %d.\n",
5067 file, linenum, MAX_HDR_HISTORY);
5068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
5070 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005071 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005072 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005073
Willy Tarreau902636f2013-03-10 19:44:48 +01005074 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005075 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005076 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005077 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005078 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005079 goto out;
5080 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005081
5082 proto = protocol_by_family(sk->ss_family);
5083 if (!proto || !proto->connect) {
5084 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5085 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
5088 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005089
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005090 if (port1 != port2) {
5091 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5092 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
5095 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005096 curproxy->conn_src.tproxy_addr = *sk;
5097 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005098 }
5099 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005100#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005101 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005102#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005103#else /* no TPROXY support */
5104 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005105 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005108#endif
5109 cur_arg += 2;
5110 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005111 }
5112
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005113 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5114#ifdef SO_BINDTODEVICE
5115 if (!*args[cur_arg + 1]) {
5116 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5117 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005120 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005121 free(curproxy->conn_src.iface_name);
5122 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5123 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005124 global.last_checks |= LSTCHK_NETADM;
5125#else
5126 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5127 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005130#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005131 cur_arg += 2;
5132 continue;
5133 }
5134 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005135 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005140 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5141 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5142 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5149 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005153
5154 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005155 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005156 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005157 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
5160 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005162 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005163 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005169 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005170 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005171 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
5174 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005176 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005177 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005183 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005184 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005188 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005190 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005191 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005193 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005194 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005195 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005197 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005198 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005200 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005201
5202 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5203 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 +01005204 }
5205 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005207 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005208 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005209 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005210 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005211
5212 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5213 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 +01005214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5218 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222
5223 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005224 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005225 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005226 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 }
5229 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005230 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005231 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005232 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005233 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
5236 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005237 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005238 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005239 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005240 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 }
5243 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005244 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005245 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005246 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005247 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
5250 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005251 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005252 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005253 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005257 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005258 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005259 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005260 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005262 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005265 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005266
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 if (curproxy == &defproxy) {
5268 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005272 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005273 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 if (*(args[1]) == 0) {
5276 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005280
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005281 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005282 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5283 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5284 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
5287 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005288 err_code |= warnif_cond_conflicts(cond,
5289 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5290 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005291 }
5292 else if (*args[2]) {
5293 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5294 file, linenum, args[0], args[2]);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005299 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005300 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005301 wl->s = strdup(args[1]);
5302 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005303 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
5305 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005306 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5308 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005312
Willy Tarreauade5ec42010-01-28 19:33:49 +01005313 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005314 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005315 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005316 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 }
5319 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005320 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005321 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005322 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005323 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 }
5326 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005327 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005328 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005329 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005330 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 }
5333 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005334 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5336 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339 }
5340
Willy Tarreauade5ec42010-01-28 19:33:49 +01005341 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005342 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005343 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005344 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 }
5347 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005348 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005349 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005350 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005351 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005353 }
5354 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005355 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005356 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005357 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005358 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005362 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005363
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 if (curproxy == &defproxy) {
5365 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005369 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005370 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 if (*(args[1]) == 0) {
5373 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
5377
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005378 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005379 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5380 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5381 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
5384 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005385 err_code |= warnif_cond_conflicts(cond,
5386 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5387 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005388 }
5389 else if (*args[2]) {
5390 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5391 file, linenum, args[0], args[2]);
5392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 }
5395
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005396 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005397 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005398 wl->s = strdup(args[1]);
5399 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 }
5401 else if (!strcmp(args[0], "errorloc") ||
5402 !strcmp(args[0], "errorloc302") ||
5403 !strcmp(args[0], "errorloc303")) { /* error location */
5404 int errnum, errlen;
5405 char *err;
5406
Willy Tarreau977b8e42006-12-29 14:19:17 +01005407 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005408 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005409
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005411 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005414 }
5415
5416 errnum = atol(args[1]);
5417 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005418 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5419 err = malloc(errlen);
5420 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005422 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5423 err = malloc(errlen);
5424 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 }
5426
Willy Tarreau0f772532006-12-23 20:51:41 +01005427 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5428 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005429 chunk_destroy(&curproxy->errmsg[rc]);
5430 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005431 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005434
5435 if (rc >= HTTP_ERR_SIZE) {
5436 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5437 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 free(err);
5439 }
5440 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005441 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5442 int errnum, errlen, fd;
5443 char *err;
5444 struct stat stat;
5445
5446 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005447 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005448
5449 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005450 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005453 }
5454
5455 fd = open(args[2], O_RDONLY);
5456 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5457 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5458 file, linenum, args[2], args[1]);
5459 if (fd >= 0)
5460 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005463 }
5464
Willy Tarreau27a674e2009-08-17 07:23:33 +02005465 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005466 errlen = stat.st_size;
5467 } else {
5468 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005469 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005470 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005471 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005472 }
5473
5474 err = malloc(errlen); /* malloc() must succeed during parsing */
5475 errnum = read(fd, err, errlen);
5476 if (errnum != errlen) {
5477 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5478 file, linenum, args[2], args[1]);
5479 close(fd);
5480 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005483 }
5484 close(fd);
5485
5486 errnum = atol(args[1]);
5487 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5488 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005489 chunk_destroy(&curproxy->errmsg[rc]);
5490 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005491 break;
5492 }
5493 }
5494
5495 if (rc >= HTTP_ERR_SIZE) {
5496 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5497 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005499 free(err);
5500 }
5501 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005502 else if (!strcmp(args[0], "compression")) {
5503 struct comp *comp;
5504 if (curproxy->comp == NULL) {
5505 comp = calloc(1, sizeof(struct comp));
5506 curproxy->comp = comp;
5507 } else {
5508 comp = curproxy->comp;
5509 }
5510
5511 if (!strcmp(args[1], "algo")) {
5512 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005513 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005514
William Lallemand82fe75c2012-10-23 10:25:10 +02005515 cur_arg = 2;
5516 if (!*args[cur_arg]) {
5517 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5518 file, linenum, args[0]);
5519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
5521 }
5522 while (*(args[cur_arg])) {
5523 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5524 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5525 file, linenum, args[0], args[cur_arg]);
5526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
5528 }
William Lallemand552df672012-11-07 13:21:47 +01005529 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5530 curproxy->comp->algos->end(&ctx);
5531 } else {
5532 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5533 file, linenum, args[0], args[cur_arg]);
5534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005537 cur_arg ++;
5538 continue;
5539 }
5540 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005541 else if (!strcmp(args[1], "offload")) {
5542 comp->offload = 1;
5543 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005544 else if (!strcmp(args[1], "type")) {
5545 int cur_arg;
5546 cur_arg = 2;
5547 if (!*args[cur_arg]) {
5548 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5549 file, linenum, args[0]);
5550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
5552 }
5553 while (*(args[cur_arg])) {
5554 comp_append_type(comp, args[cur_arg]);
5555 cur_arg ++;
5556 continue;
5557 }
5558 }
5559 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005560 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005561 file, linenum, args[0]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005567 struct cfg_kw_list *kwl;
5568 int index;
5569
5570 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5571 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5572 if (kwl->kw[index].section != CFG_LISTEN)
5573 continue;
5574 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5575 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005576 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005577 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005578 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005581 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005582 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005583 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_WARN;
5585 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005586 }
Willy Tarreau93893792009-07-23 13:19:11 +02005587 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005588 }
5589 }
5590 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005591
Willy Tarreau6daf3432008-01-22 16:44:08 +01005592 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 }
Willy Tarreau93893792009-07-23 13:19:11 +02005596 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005597 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005598 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599}
5600
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005601int
5602cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5603{
5604
5605 int err_code = 0;
5606 const char *err;
5607
5608 if (!strcmp(args[0], "userlist")) { /* new userlist */
5609 struct userlist *newul;
5610
5611 if (!*args[1]) {
5612 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5613 file, linenum, args[0]);
5614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
5616 }
5617
5618 err = invalid_char(args[1]);
5619 if (err) {
5620 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5621 file, linenum, *err, args[0], args[1]);
5622 err_code |= ERR_ALERT | ERR_FATAL;
5623 goto out;
5624 }
5625
5626 for (newul = userlist; newul; newul = newul->next)
5627 if (!strcmp(newul->name, args[1])) {
5628 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5629 file, linenum, args[1]);
5630 err_code |= ERR_WARN;
5631 goto out;
5632 }
5633
5634 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5635 if (!newul) {
5636 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5637 err_code |= ERR_ALERT | ERR_ABORT;
5638 goto out;
5639 }
5640
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005641 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005642 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005643 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5644 err_code |= ERR_ALERT | ERR_ABORT;
5645 goto out;
5646 }
5647
5648 newul->next = userlist;
5649 userlist = newul;
5650
5651 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005652 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005653 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005654 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005655
5656 if (!*args[1]) {
5657 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5658 file, linenum, args[0]);
5659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
5661 }
5662
5663 err = invalid_char(args[1]);
5664 if (err) {
5665 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5666 file, linenum, *err, args[0], args[1]);
5667 err_code |= ERR_ALERT | ERR_FATAL;
5668 goto out;
5669 }
5670
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005671 for (ag = userlist->groups; ag; ag = ag->next)
5672 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005673 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5674 file, linenum, args[1], userlist->name);
5675 err_code |= ERR_ALERT;
5676 goto out;
5677 }
5678
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005679 ag = calloc(1, sizeof(*ag));
5680 if (!ag) {
5681 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5682 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005683 goto out;
5684 }
5685
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005686 ag->name = strdup(args[1]);
5687 if (!ag) {
5688 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5689 err_code |= ERR_ALERT | ERR_ABORT;
5690 goto out;
5691 }
5692
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005693 cur_arg = 2;
5694
5695 while (*args[cur_arg]) {
5696 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005697 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005698 cur_arg += 2;
5699 continue;
5700 } else {
5701 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5702 file, linenum, args[0]);
5703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
5705 }
5706 }
5707
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005708 ag->next = userlist->groups;
5709 userlist->groups = ag;
5710
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005711 } else if (!strcmp(args[0], "user")) { /* new user */
5712 struct auth_users *newuser;
5713 int cur_arg;
5714
5715 if (!*args[1]) {
5716 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5717 file, linenum, args[0]);
5718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
5720 }
5721
5722 for (newuser = userlist->users; newuser; newuser = newuser->next)
5723 if (!strcmp(newuser->user, args[1])) {
5724 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5725 file, linenum, args[1], userlist->name);
5726 err_code |= ERR_ALERT;
5727 goto out;
5728 }
5729
5730 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5731 if (!newuser) {
5732 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5733 err_code |= ERR_ALERT | ERR_ABORT;
5734 goto out;
5735 }
5736
5737 newuser->user = strdup(args[1]);
5738
5739 newuser->next = userlist->users;
5740 userlist->users = newuser;
5741
5742 cur_arg = 2;
5743
5744 while (*args[cur_arg]) {
5745 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005746#ifdef CONFIG_HAP_CRYPT
5747 if (!crypt("", args[cur_arg + 1])) {
5748 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5749 file, linenum, newuser->user);
5750 err_code |= ERR_ALERT | ERR_FATAL;
5751 goto out;
5752 }
5753#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005754 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5755 file, linenum);
5756 err_code |= ERR_ALERT;
5757#endif
5758 newuser->pass = strdup(args[cur_arg + 1]);
5759 cur_arg += 2;
5760 continue;
5761 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5762 newuser->pass = strdup(args[cur_arg + 1]);
5763 newuser->flags |= AU_O_INSECURE;
5764 cur_arg += 2;
5765 continue;
5766 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005767 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005768 cur_arg += 2;
5769 continue;
5770 } else {
5771 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5772 file, linenum, args[0]);
5773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
5775 }
5776 }
5777 } else {
5778 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5779 err_code |= ERR_ALERT | ERR_FATAL;
5780 }
5781
5782out:
5783 return err_code;
5784}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785
5786/*
5787 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005788 * Returns the error code, 0 if OK, or any combination of :
5789 * - ERR_ABORT: must abort ASAP
5790 * - ERR_FATAL: we can continue parsing but not start the service
5791 * - ERR_WARN: a warning has been emitted
5792 * - ERR_ALERT: an alert has been emitted
5793 * Only the two first ones can stop processing, the two others are just
5794 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005796int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005798 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 FILE *f;
5800 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005801 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005802 struct cfg_section *cs = NULL;
5803 struct cfg_section *ics;
5804
5805 /* Register internal sections */
5806 if (!cfg_register_section("listen", cfg_parse_listen) ||
5807 !cfg_register_section("frontend", cfg_parse_listen) ||
5808 !cfg_register_section("backend", cfg_parse_listen) ||
5809 !cfg_register_section("ruleset", cfg_parse_listen) ||
5810 !cfg_register_section("defaults", cfg_parse_listen) ||
5811 !cfg_register_section("global", cfg_parse_global) ||
5812 !cfg_register_section("userlist", cfg_parse_users) ||
5813 !cfg_register_section("peers", cfg_parse_peers))
5814 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 if ((f=fopen(file,"r")) == NULL)
5817 return -1;
5818
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005819 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005820 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005821 char *end;
5822 char *args[MAX_LINE_ARGS + 1];
5823 char *line = thisline;
5824
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 linenum++;
5826
5827 end = line + strlen(line);
5828
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005829 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5830 /* Check if we reached the limit and the last char is not \n.
5831 * Watch out for the last line without the terminating '\n'!
5832 */
5833 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005834 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005835 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005836 }
5837
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005839 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 line++;
5841
5842 arg = 0;
5843 args[arg] = line;
5844
5845 while (*line && arg < MAX_LINE_ARGS) {
5846 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5847 * C equivalent value. Other combinations left unchanged (eg: \1).
5848 */
5849 if (*line == '\\') {
5850 int skip = 0;
5851 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5852 *line = line[1];
5853 skip = 1;
5854 }
5855 else if (line[1] == 'r') {
5856 *line = '\r';
5857 skip = 1;
5858 }
5859 else if (line[1] == 'n') {
5860 *line = '\n';
5861 skip = 1;
5862 }
5863 else if (line[1] == 't') {
5864 *line = '\t';
5865 skip = 1;
5866 }
5867 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005868 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 unsigned char hex1, hex2;
5870 hex1 = toupper(line[2]) - '0';
5871 hex2 = toupper(line[3]) - '0';
5872 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5873 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5874 *line = (hex1<<4) + hex2;
5875 skip = 3;
5876 }
5877 else {
5878 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005879 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 }
5881 }
5882 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005883 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 end -= skip;
5885 }
5886 line++;
5887 }
5888 else if (*line == '#' || *line == '\n' || *line == '\r') {
5889 /* end of string, end of loop */
5890 *line = 0;
5891 break;
5892 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005893 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005895 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005896 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 line++;
5898 args[++arg] = line;
5899 }
5900 else {
5901 line++;
5902 }
5903 }
5904
5905 /* empty line */
5906 if (!**args)
5907 continue;
5908
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005909 if (*line) {
5910 /* we had to stop due to too many args.
5911 * Let's terminate the string, print the offending part then cut the
5912 * last arg.
5913 */
5914 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5915 line++;
5916 *line = '\0';
5917
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005918 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005919 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005920 err_code |= ERR_ALERT | ERR_FATAL;
5921 args[arg] = line;
5922 }
5923
Willy Tarreau540abe42007-05-02 20:50:16 +02005924 /* zero out remaining args and ensure that at least one entry
5925 * is zeroed out.
5926 */
5927 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928 args[arg] = line;
5929 }
5930
Willy Tarreau3842f002009-06-14 11:39:52 +02005931 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005932 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005933 char *tmp;
5934
Willy Tarreau3842f002009-06-14 11:39:52 +02005935 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005936 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005937 for (arg=0; *args[arg+1]; arg++)
5938 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005939 *tmp = '\0'; // fix the next arg to \0
5940 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005941 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005942 else if (!strcmp(args[0], "default")) {
5943 kwm = KWM_DEF;
5944 for (arg=0; *args[arg+1]; arg++)
5945 args[arg] = args[arg+1]; // shift args after inversion
5946 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005947
William Lallemand0f99e342011-10-12 17:50:54 +02005948 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5949 strcmp(args[0], "log") != 0) {
5950 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005951 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005952 }
5953
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005954 /* detect section start */
5955 list_for_each_entry(ics, &sections, list) {
5956 if (strcmp(args[0], ics->section_name) == 0) {
5957 cursection = ics->section_name;
5958 cs = ics;
5959 break;
5960 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005961 }
5962
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005964 if (cs)
5965 err_code |= cs->section_parser(file, linenum, args, kwm);
5966 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005967 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005968 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005970
5971 if (err_code & ERR_ABORT)
5972 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005974 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005976 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005977}
5978
Willy Tarreau5436afc2014-09-16 12:17:36 +02005979/* This function propagates processes from frontend <from> to backend <to> so
5980 * that it is always guaranteed that a backend pointed to by a frontend is
5981 * bound to all of its processes. After that, if the target is a "listen"
5982 * instance, the function recursively descends the target's own targets along
5983 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
5984 * checked first to ensure that <to> is already bound to all processes of
5985 * <from>, there is no risk of looping and we ensure to follow the shortest
5986 * path to the destination.
5987 *
5988 * It is possible to set <to> to NULL for the first call so that the function
5989 * takes care of visiting the initial frontend in <from>.
5990 *
5991 * It is important to note that the function relies on the fact that all names
5992 * have already been resolved.
5993 */
5994void propagate_processes(struct proxy *from, struct proxy *to)
5995{
5996 struct switching_rule *rule;
5997 struct hdr_exp *exp;
5998
5999 if (to) {
6000 /* check whether we need to go down */
6001 if (from->bind_proc &&
6002 (from->bind_proc & to->bind_proc) == from->bind_proc)
6003 return;
6004
6005 if (!from->bind_proc && !to->bind_proc)
6006 return;
6007
6008 to->bind_proc = from->bind_proc ?
6009 (to->bind_proc | from->bind_proc) : 0;
6010
6011 /* now propagate down */
6012 from = to;
6013 }
6014
Willy Tarreau7110f382014-12-18 13:56:26 +01006015 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006016 return;
6017
Willy Tarreaued061c02014-12-18 14:00:43 +01006018 if (from->state == PR_STSTOPPED)
6019 return;
6020
Willy Tarreau5436afc2014-09-16 12:17:36 +02006021 /* default_backend */
6022 if (from->defbe.be)
6023 propagate_processes(from, from->defbe.be);
6024
6025 /* use_backend */
6026 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006027 if (rule->dynamic)
6028 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006029 to = rule->be.backend;
6030 propagate_processes(from, to);
6031 }
6032
6033 /* reqsetbe */
6034 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6035 if (exp->action != ACT_SETBE)
6036 continue;
6037 to = (struct proxy *)exp->replace;
6038 propagate_processes(from, to);
6039 }
6040}
6041
Willy Tarreaubb925012009-07-23 13:36:36 +02006042/*
6043 * Returns the error code, 0 if OK, or any combination of :
6044 * - ERR_ABORT: must abort ASAP
6045 * - ERR_FATAL: we can continue parsing but not start the service
6046 * - ERR_WARN: a warning has been emitted
6047 * - ERR_ALERT: an alert has been emitted
6048 * Only the two first ones can stop processing, the two others are just
6049 * indicators.
6050 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006051int check_config_validity()
6052{
6053 int cfgerr = 0;
6054 struct proxy *curproxy = NULL;
6055 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006056 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006057 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006058 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006060 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061 /*
6062 * Now, check for the integrity of all that we have collected.
6063 */
6064
6065 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006066 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067
Willy Tarreau193b8c62012-11-22 00:17:38 +01006068 if (!global.tune.max_http_hdr)
6069 global.tune.max_http_hdr = MAX_HTTP_HDR;
6070
6071 if (!global.tune.cookie_len)
6072 global.tune.cookie_len = CAPTURE_LEN;
6073
6074 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6075
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006076 /* Post initialisation of the users and groups lists. */
6077 err_code = userlist_postinit();
6078 if (err_code != ERR_NONE)
6079 goto out;
6080
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006081 /* first, we will invert the proxy list order */
6082 curproxy = NULL;
6083 while (proxy) {
6084 struct proxy *next;
6085
6086 next = proxy->next;
6087 proxy->next = curproxy;
6088 curproxy = proxy;
6089 if (!next)
6090 break;
6091 proxy = next;
6092 }
6093
Willy Tarreau91b00c22014-09-16 13:41:21 +02006094 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006095 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006096 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006097 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006098 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006099 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006100 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006101
Willy Tarreau050536d2012-10-04 08:47:34 +02006102 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006103 /* proxy ID not set, use automatic numbering with first
6104 * spare entry starting with next_pxid.
6105 */
6106 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6107 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6108 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006109 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006110 next_pxid++;
6111
Willy Tarreau55ea7572007-06-17 19:56:27 +02006112
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006114 /* ensure we don't keep listeners uselessly bound */
6115 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006116 free((void *)curproxy->table.peers.name);
6117 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118 continue;
6119 }
6120
Willy Tarreau102df612014-05-07 23:56:38 +02006121 /* Check multi-process mode compatibility for the current proxy */
6122
6123 if (curproxy->bind_proc) {
6124 /* an explicit bind-process was specified, let's check how many
6125 * processes remain.
6126 */
6127 nbproc = popcount(curproxy->bind_proc);
6128
6129 curproxy->bind_proc &= nbits(global.nbproc);
6130 if (!curproxy->bind_proc && nbproc == 1) {
6131 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);
6132 curproxy->bind_proc = 1;
6133 }
6134 else if (!curproxy->bind_proc && nbproc > 1) {
6135 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);
6136 curproxy->bind_proc = 0;
6137 }
6138 }
6139
Willy Tarreau3d209582014-05-09 17:06:11 +02006140 /* check and reduce the bind-proc of each listener */
6141 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6142 unsigned long mask;
6143
6144 if (!bind_conf->bind_proc)
6145 continue;
6146
6147 mask = nbits(global.nbproc);
6148 if (curproxy->bind_proc)
6149 mask &= curproxy->bind_proc;
6150 /* mask cannot be null here thanks to the previous checks */
6151
6152 nbproc = popcount(bind_conf->bind_proc);
6153 bind_conf->bind_proc &= mask;
6154
6155 if (!bind_conf->bind_proc && nbproc == 1) {
6156 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",
6157 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6158 bind_conf->bind_proc = mask & ~(mask - 1);
6159 }
6160 else if (!bind_conf->bind_proc && nbproc > 1) {
6161 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",
6162 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6163 bind_conf->bind_proc = 0;
6164 }
6165 }
6166
Willy Tarreau102df612014-05-07 23:56:38 +02006167 if (global.nbproc > 1 && curproxy->table.peers.name) {
6168 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6169 curproxy->id);
6170 cfgerr++;
6171 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006172
Willy Tarreauff01a212009-03-15 13:46:16 +01006173 switch (curproxy->mode) {
6174 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006175 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006176 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006177 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6178 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006179 cfgerr++;
6180 }
6181
6182 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006183 Warning("config : servers will be ignored for %s '%s'.\n",
6184 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006185 break;
6186
6187 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006188 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006189 break;
6190
6191 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006192 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006193 break;
6194 }
6195
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006196 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006197 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006198 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006199 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6200 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006201 cfgerr++;
6202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006204 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006205 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6206 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006207 cfgerr++;
6208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006210 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006211 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6212 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006213 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006214 }
6215 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006216 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006217 /* If no LB algo is set in a backend, and we're not in
6218 * transparent mode, dispatch mode nor proxy mode, we
6219 * want to use balance roundrobin by default.
6220 */
6221 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6222 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006223 }
6224 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006225
Willy Tarreau1620ec32011-08-06 17:05:02 +02006226 if (curproxy->options & PR_O_DISPATCH)
6227 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6228 else if (curproxy->options & PR_O_HTTP_PROXY)
6229 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6230 else if (curproxy->options & PR_O_TRANSP)
6231 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006232
Willy Tarreau1620ec32011-08-06 17:05:02 +02006233 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6234 if (curproxy->options & PR_O_DISABLE404) {
6235 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6236 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6237 err_code |= ERR_WARN;
6238 curproxy->options &= ~PR_O_DISABLE404;
6239 }
6240 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6241 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6242 "send-state", proxy_type_str(curproxy), curproxy->id);
6243 err_code |= ERR_WARN;
6244 curproxy->options &= ~PR_O2_CHK_SNDST;
6245 }
Willy Tarreauef781042010-01-27 11:53:01 +01006246 }
6247
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006248 /* if a default backend was specified, let's find it */
6249 if (curproxy->defbe.name) {
6250 struct proxy *target;
6251
Alex Williams96532db2009-11-01 21:27:13 -05006252 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006253 if (!target) {
6254 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6255 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006256 cfgerr++;
6257 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006258 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6259 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006260 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006261 } else {
6262 free(curproxy->defbe.name);
6263 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006264
6265 /* Emit a warning if this proxy also has some servers */
6266 if (curproxy->srv) {
6267 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6268 curproxy->id);
6269 err_code |= ERR_WARN;
6270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 }
6272 }
6273
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006274 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006275 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6276 /* map jump target for ACT_SETBE in req_rep chain */
6277 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006278 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006279 struct proxy *target;
6280
Willy Tarreaua496b602006-12-17 23:15:24 +01006281 if (exp->action != ACT_SETBE)
6282 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006283
Alex Williams96532db2009-11-01 21:27:13 -05006284 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006285 if (!target) {
6286 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6287 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006288 cfgerr++;
6289 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006290 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6291 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006292 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006293 } else {
6294 free((void *)exp->replace);
6295 exp->replace = (const char *)target;
6296 }
6297 }
6298 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006299
6300 /* find the target proxy for 'use_backend' rules */
6301 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006302 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006303 struct logformat_node *node;
6304 char *pxname;
6305
6306 /* Try to parse the string as a log format expression. If the result
6307 * of the parsing is only one entry containing a simple string, then
6308 * it's a standard string corresponding to a static rule, thus the
6309 * parsing is cancelled and be.name is restored to be resolved.
6310 */
6311 pxname = rule->be.name;
6312 LIST_INIT(&rule->be.expr);
6313 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6314 curproxy->conf.args.file, curproxy->conf.args.line);
6315 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6316
6317 if (!LIST_ISEMPTY(&rule->be.expr)) {
6318 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6319 rule->dynamic = 1;
6320 free(pxname);
6321 continue;
6322 }
6323 /* simple string: free the expression and fall back to static rule */
6324 free(node->arg);
6325 free(node);
6326 }
6327
6328 rule->dynamic = 0;
6329 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006330
Alex Williams96532db2009-11-01 21:27:13 -05006331 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006332
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006333 if (!target) {
6334 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6335 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006336 cfgerr++;
6337 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006338 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6339 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006340 cfgerr++;
6341 } else {
6342 free((void *)rule->be.name);
6343 rule->be.backend = target;
6344 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006345 }
6346
Willy Tarreau5436afc2014-09-16 12:17:36 +02006347 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006348 list_for_each_entry(srule, &curproxy->server_rules, list) {
6349 struct server *target = findserver(curproxy, srule->srv.name);
6350
6351 if (!target) {
6352 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6353 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6354 cfgerr++;
6355 continue;
6356 }
6357 free((void *)srule->srv.name);
6358 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006359 }
6360
Emeric Brunb982a3d2010-01-04 15:45:53 +01006361 /* find the target table for 'stick' rules */
6362 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6363 struct proxy *target;
6364
Emeric Brun1d33b292010-01-04 15:47:17 +01006365 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6366 if (mrule->flags & STK_IS_STORE)
6367 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6368
Emeric Brunb982a3d2010-01-04 15:45:53 +01006369 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006370 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006371 else
6372 target = curproxy;
6373
6374 if (!target) {
6375 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6376 curproxy->id, mrule->table.name);
6377 cfgerr++;
6378 }
6379 else if (target->table.size == 0) {
6380 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6381 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6382 cfgerr++;
6383 }
Willy Tarreau12785782012-04-27 21:37:17 +02006384 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6385 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006386 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6387 cfgerr++;
6388 }
6389 else {
6390 free((void *)mrule->table.name);
6391 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006392 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006393 }
6394 }
6395
6396 /* find the target table for 'store response' rules */
6397 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6398 struct proxy *target;
6399
Emeric Brun1d33b292010-01-04 15:47:17 +01006400 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6401
Emeric Brunb982a3d2010-01-04 15:45:53 +01006402 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006403 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006404 else
6405 target = curproxy;
6406
6407 if (!target) {
6408 Alert("Proxy '%s': unable to find store table '%s'.\n",
6409 curproxy->id, mrule->table.name);
6410 cfgerr++;
6411 }
6412 else if (target->table.size == 0) {
6413 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6414 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6415 cfgerr++;
6416 }
Willy Tarreau12785782012-04-27 21:37:17 +02006417 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6418 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006419 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6420 cfgerr++;
6421 }
6422 else {
6423 free((void *)mrule->table.name);
6424 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006425 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006426 }
6427 }
6428
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006429 /* find the target table for 'tcp-request' layer 4 rules */
6430 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6431 struct proxy *target;
6432
Willy Tarreaub4c84932013-07-23 19:15:30 +02006433 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006434 continue;
6435
6436 if (trule->act_prm.trk_ctr.table.n)
6437 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6438 else
6439 target = curproxy;
6440
6441 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006442 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6443 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006444 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006445 cfgerr++;
6446 }
6447 else if (target->table.size == 0) {
6448 Alert("Proxy '%s': table '%s' used but not configured.\n",
6449 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6450 cfgerr++;
6451 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006452 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6453 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6454 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 +01006455 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006456 cfgerr++;
6457 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006458 else {
6459 free(trule->act_prm.trk_ctr.table.n);
6460 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006461 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006462 * to pass a list of counters to track and allocate them right here using
6463 * stktable_alloc_data_type().
6464 */
6465 }
6466 }
6467
Willy Tarreaud1f96522010-08-03 19:34:32 +02006468 /* find the target table for 'tcp-request' layer 6 rules */
6469 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6470 struct proxy *target;
6471
Willy Tarreaub4c84932013-07-23 19:15:30 +02006472 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006473 continue;
6474
6475 if (trule->act_prm.trk_ctr.table.n)
6476 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6477 else
6478 target = curproxy;
6479
6480 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006481 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6482 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006483 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006484 cfgerr++;
6485 }
6486 else if (target->table.size == 0) {
6487 Alert("Proxy '%s': table '%s' used but not configured.\n",
6488 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6489 cfgerr++;
6490 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006491 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6492 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6493 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 +01006494 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006495 cfgerr++;
6496 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006497 else {
6498 free(trule->act_prm.trk_ctr.table.n);
6499 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006500 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006501 * to pass a list of counters to track and allocate them right here using
6502 * stktable_alloc_data_type().
6503 */
6504 }
6505 }
6506
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006507 /* move any "block" rules at the beginning of the http-request rules */
6508 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6509 /* insert block_rules into http_req_rules at the beginning */
6510 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6511 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6512 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6513 curproxy->http_req_rules.n = curproxy->block_rules.n;
6514 LIST_INIT(&curproxy->block_rules);
6515 }
6516
Emeric Brun32da3c42010-09-23 18:39:19 +02006517 if (curproxy->table.peers.name) {
6518 struct peers *curpeers = peers;
6519
6520 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6521 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6522 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006523 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006524 break;
6525 }
6526 }
6527
6528 if (!curpeers) {
6529 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6530 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006531 free((void *)curproxy->table.peers.name);
6532 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006533 cfgerr++;
6534 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006535 else if (curpeers->state == PR_STSTOPPED) {
6536 /* silently disable this peers section */
6537 curproxy->table.peers.p = NULL;
6538 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006539 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006540 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6541 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006542 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006543 cfgerr++;
6544 }
6545 }
6546
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006547 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006548 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006549 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6550 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6551 "proxy", curproxy->id);
6552 cfgerr++;
6553 goto out_uri_auth_compat;
6554 }
6555
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006556 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006557 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006558 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006559 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006560
Willy Tarreau95fa4692010-02-01 13:05:50 +01006561 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6562 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006563
6564 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006565 uri_auth_compat_req[i++] = "realm";
6566 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6567 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006568
Willy Tarreau95fa4692010-02-01 13:05:50 +01006569 uri_auth_compat_req[i++] = "unless";
6570 uri_auth_compat_req[i++] = "{";
6571 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6572 uri_auth_compat_req[i++] = "}";
6573 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006574
Willy Tarreauff011f22011-01-06 17:51:27 +01006575 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6576 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006577 cfgerr++;
6578 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006579 }
6580
Willy Tarreauff011f22011-01-06 17:51:27 +01006581 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006582
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006583 if (curproxy->uri_auth->auth_realm) {
6584 free(curproxy->uri_auth->auth_realm);
6585 curproxy->uri_auth->auth_realm = NULL;
6586 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006587
6588 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006589 }
6590out_uri_auth_compat:
6591
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006592 /* compile the log format */
6593 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006594 if (curproxy->conf.logformat_string != default_http_log_format &&
6595 curproxy->conf.logformat_string != default_tcp_log_format &&
6596 curproxy->conf.logformat_string != clf_http_log_format)
6597 free(curproxy->conf.logformat_string);
6598 curproxy->conf.logformat_string = NULL;
6599 free(curproxy->conf.lfs_file);
6600 curproxy->conf.lfs_file = NULL;
6601 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006602 }
6603
Willy Tarreau62a61232013-04-12 18:13:46 +02006604 if (curproxy->conf.logformat_string) {
6605 curproxy->conf.args.ctx = ARGC_LOG;
6606 curproxy->conf.args.file = curproxy->conf.lfs_file;
6607 curproxy->conf.args.line = curproxy->conf.lfs_line;
6608 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006609 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006610 curproxy->conf.args.file = NULL;
6611 curproxy->conf.args.line = 0;
6612 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006613
Willy Tarreau62a61232013-04-12 18:13:46 +02006614 if (curproxy->conf.uniqueid_format_string) {
6615 curproxy->conf.args.ctx = ARGC_UIF;
6616 curproxy->conf.args.file = curproxy->conf.uif_file;
6617 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006618 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006619 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006620 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006621 curproxy->conf.args.file = NULL;
6622 curproxy->conf.args.line = 0;
6623 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006624
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006625 /* only now we can check if some args remain unresolved.
6626 * This must be done after the users and groups resolution.
6627 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006628 cfgerr += smp_resolve_args(curproxy);
6629 if (!cfgerr)
6630 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006631
Willy Tarreau2738a142006-07-08 17:28:09 +02006632 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006633 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006634 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006635 (!curproxy->timeout.connect ||
6636 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006637 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006638 " | While not properly invalid, you will certainly encounter various problems\n"
6639 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006640 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006641 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006642 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006643 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006644
Willy Tarreau1fa31262007-12-03 00:36:16 +01006645 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6646 * We must still support older configurations, so let's find out whether those
6647 * parameters have been set or must be copied from contimeouts.
6648 */
6649 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006650 if (!curproxy->timeout.tarpit ||
6651 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006652 /* tarpit timeout not set. We search in the following order:
6653 * default.tarpit, curr.connect, default.connect.
6654 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006655 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006656 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006657 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006658 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006659 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006660 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006661 }
6662 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006663 (!curproxy->timeout.queue ||
6664 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006665 /* queue timeout not set. We search in the following order:
6666 * default.queue, curr.connect, default.connect.
6667 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006668 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006669 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006670 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006671 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006672 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006673 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006674 }
6675 }
6676
Willy Tarreau1620ec32011-08-06 17:05:02 +02006677 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006678 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6679 curproxy->check_req = (char *)malloc(curproxy->check_len);
6680 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006681 }
6682
Willy Tarreau215663d2014-06-13 18:30:23 +02006683 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6684 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6685 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6686 proxy_type_str(curproxy), curproxy->id);
6687 err_code |= ERR_WARN;
6688 }
6689
Willy Tarreau193b8c62012-11-22 00:17:38 +01006690 /* ensure that cookie capture length is not too large */
6691 if (curproxy->capture_len >= global.tune.cookie_len) {
6692 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6693 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6694 err_code |= ERR_WARN;
6695 curproxy->capture_len = global.tune.cookie_len - 1;
6696 }
6697
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006698 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006699 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006700 curproxy->req_cap_pool = create_pool("ptrcap",
6701 curproxy->nb_req_cap * sizeof(char *),
6702 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006703 }
6704
6705 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006706 curproxy->rsp_cap_pool = create_pool("ptrcap",
6707 curproxy->nb_rsp_cap * sizeof(char *),
6708 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006709 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006710
Willy Tarreaubaaee002006-06-26 02:48:02 +02006711 /* first, we will invert the servers list order */
6712 newsrv = NULL;
6713 while (curproxy->srv) {
6714 struct server *next;
6715
6716 next = curproxy->srv->next;
6717 curproxy->srv->next = newsrv;
6718 newsrv = curproxy->srv;
6719 if (!next)
6720 break;
6721 curproxy->srv = next;
6722 }
6723
Willy Tarreau17edc812014-01-03 12:14:34 +01006724 /* Check that no server name conflicts. This causes trouble in the stats.
6725 * We only emit a warning for the first conflict affecting each server,
6726 * in order to avoid combinatory explosion if all servers have the same
6727 * name. We do that only for servers which do not have an explicit ID,
6728 * because these IDs were made also for distinguishing them and we don't
6729 * want to annoy people who correctly manage them.
6730 */
6731 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6732 struct server *other_srv;
6733
6734 if (newsrv->puid)
6735 continue;
6736
6737 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6738 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6739 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6740 newsrv->conf.file, newsrv->conf.line,
6741 proxy_type_str(curproxy), curproxy->id,
6742 newsrv->id, other_srv->conf.line);
6743 break;
6744 }
6745 }
6746 }
6747
Willy Tarreaudd701652010-05-25 23:03:02 +02006748 /* assign automatic UIDs to servers which don't have one yet */
6749 next_id = 1;
6750 newsrv = curproxy->srv;
6751 while (newsrv != NULL) {
6752 if (!newsrv->puid) {
6753 /* server ID not set, use automatic numbering with first
6754 * spare entry starting with next_svid.
6755 */
6756 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6757 newsrv->conf.id.key = newsrv->puid = next_id;
6758 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6759 }
6760 next_id++;
6761 newsrv = newsrv->next;
6762 }
6763
Willy Tarreau20697042007-11-15 23:26:18 +01006764 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006765 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006766
Willy Tarreau62c3be22012-01-20 13:12:32 +01006767 /*
6768 * If this server supports a maxconn parameter, it needs a dedicated
6769 * tasks to fill the emptied slots when a connection leaves.
6770 * Also, resolve deferred tracking dependency if needed.
6771 */
6772 newsrv = curproxy->srv;
6773 while (newsrv != NULL) {
6774 if (newsrv->minconn > newsrv->maxconn) {
6775 /* Only 'minconn' was specified, or it was higher than or equal
6776 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6777 * this will avoid further useless expensive computations.
6778 */
6779 newsrv->maxconn = newsrv->minconn;
6780 } else if (newsrv->maxconn && !newsrv->minconn) {
6781 /* minconn was not specified, so we set it to maxconn */
6782 newsrv->minconn = newsrv->maxconn;
6783 }
6784
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006785#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006786 if (newsrv->use_ssl || newsrv->check.use_ssl)
6787 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006788#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006789
Willy Tarreau2f075e92013-12-03 11:11:34 +01006790 /* set the check type on the server */
6791 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6792
Willy Tarreau62c3be22012-01-20 13:12:32 +01006793 if (newsrv->trackit) {
6794 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006795 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006796 char *pname, *sname;
6797
6798 pname = newsrv->trackit;
6799 sname = strrchr(pname, '/');
6800
6801 if (sname)
6802 *sname++ = '\0';
6803 else {
6804 sname = pname;
6805 pname = NULL;
6806 }
6807
6808 if (pname) {
6809 px = findproxy(pname, PR_CAP_BE);
6810 if (!px) {
6811 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6812 proxy_type_str(curproxy), curproxy->id,
6813 newsrv->id, pname);
6814 cfgerr++;
6815 goto next_srv;
6816 }
6817 } else
6818 px = curproxy;
6819
6820 srv = findserver(px, sname);
6821 if (!srv) {
6822 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6823 proxy_type_str(curproxy), curproxy->id,
6824 newsrv->id, sname);
6825 cfgerr++;
6826 goto next_srv;
6827 }
6828
Willy Tarreau32091232014-05-16 13:52:00 +02006829 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6830 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6831 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006832 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006833 "tracking as it does not have any check nor agent enabled.\n",
6834 proxy_type_str(curproxy), curproxy->id,
6835 newsrv->id, px->id, srv->id);
6836 cfgerr++;
6837 goto next_srv;
6838 }
6839
6840 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6841
6842 if (loop) {
6843 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6844 "belongs to a tracking chain looping back to %s/%s.\n",
6845 proxy_type_str(curproxy), curproxy->id,
6846 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006847 cfgerr++;
6848 goto next_srv;
6849 }
6850
6851 if (curproxy != px &&
6852 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6853 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6854 "tracking: disable-on-404 option inconsistency.\n",
6855 proxy_type_str(curproxy), curproxy->id,
6856 newsrv->id, px->id, srv->id);
6857 cfgerr++;
6858 goto next_srv;
6859 }
6860
6861 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006862 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006863 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006864 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006865 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006866 }
6867
6868 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006869 newsrv->tracknext = srv->trackers;
6870 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006871
6872 free(newsrv->trackit);
6873 newsrv->trackit = NULL;
6874 }
6875 next_srv:
6876 newsrv = newsrv->next;
6877 }
6878
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006879 /* We have to initialize the server lookup mechanism depending
6880 * on what LB algorithm was choosen.
6881 */
6882
6883 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6884 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6885 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006886 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6887 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6888 init_server_map(curproxy);
6889 } else {
6890 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6891 fwrr_init_server_groups(curproxy);
6892 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006893 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006894
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006895 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006896 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6897 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6898 fwlc_init_server_tree(curproxy);
6899 } else {
6900 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6901 fas_init_server_tree(curproxy);
6902 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006903 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006904
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006905 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006906 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6907 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6908 chash_init_server_tree(curproxy);
6909 } else {
6910 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6911 init_server_map(curproxy);
6912 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006913 break;
6914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006915
6916 if (curproxy->options & PR_O_LOGASAP)
6917 curproxy->to_log &= ~LW_BYTES;
6918
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006919 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006920 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006921 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6922 proxy_type_str(curproxy), curproxy->id);
6923 err_code |= ERR_WARN;
6924 }
6925
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006926 if (curproxy->mode != PR_MODE_HTTP) {
6927 int optnum;
6928
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006929 if (curproxy->uri_auth) {
6930 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6931 proxy_type_str(curproxy), curproxy->id);
6932 err_code |= ERR_WARN;
6933 curproxy->uri_auth = NULL;
6934 }
6935
Willy Tarreau87cf5142011-08-19 22:57:24 +02006936 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006937 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6938 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6939 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006940 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006941 }
6942
6943 if (curproxy->options & PR_O_ORGTO) {
6944 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6945 "originalto", proxy_type_str(curproxy), curproxy->id);
6946 err_code |= ERR_WARN;
6947 curproxy->options &= ~PR_O_ORGTO;
6948 }
6949
6950 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6951 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6952 (curproxy->cap & cfg_opts[optnum].cap) &&
6953 (curproxy->options & cfg_opts[optnum].val)) {
6954 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6955 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6956 err_code |= ERR_WARN;
6957 curproxy->options &= ~cfg_opts[optnum].val;
6958 }
6959 }
6960
6961 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6962 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6963 (curproxy->cap & cfg_opts2[optnum].cap) &&
6964 (curproxy->options2 & cfg_opts2[optnum].val)) {
6965 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6966 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6967 err_code |= ERR_WARN;
6968 curproxy->options2 &= ~cfg_opts2[optnum].val;
6969 }
6970 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006971
Pieter Baauwd551fb52013-05-08 22:49:23 +02006972#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006973 if (curproxy->conn_src.bind_hdr_occ) {
6974 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006975 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006976 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006977 err_code |= ERR_WARN;
6978 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006979#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006980 }
6981
Willy Tarreaubaaee002006-06-26 02:48:02 +02006982 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006983 * ensure that we're not cross-dressing a TCP server into HTTP.
6984 */
6985 newsrv = curproxy->srv;
6986 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006987 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006988 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6989 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006990 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006991 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006992
Willy Tarreau0cec3312011-10-31 13:49:26 +01006993 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6994 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6995 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6996 err_code |= ERR_WARN;
6997 }
6998
Willy Tarreauc93cd162014-05-13 15:54:22 +02006999 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007000 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7001 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7002 err_code |= ERR_WARN;
7003 }
7004
Pieter Baauwd551fb52013-05-08 22:49:23 +02007005#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007006 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7007 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007008 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 +01007009 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007010 err_code |= ERR_WARN;
7011 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007012#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007013 newsrv = newsrv->next;
7014 }
7015
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007016 /* check if we have a frontend with "tcp-request content" looking at L7
7017 * with no inspect-delay
7018 */
7019 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7020 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7021 if (trule->action == TCP_ACT_CAPTURE &&
7022 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7023 break;
7024 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7025 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7026 break;
7027 }
7028
7029 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7030 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7031 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7032 " This means that these rules will randomly find their contents. This can be fixed by"
7033 " setting the tcp-request inspect-delay.\n",
7034 proxy_type_str(curproxy), curproxy->id);
7035 err_code |= ERR_WARN;
7036 }
7037 }
7038
Willy Tarreauc1a21672009-08-16 22:37:44 +02007039 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007040 if (!curproxy->accept)
7041 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007042
Willy Tarreauc1a21672009-08-16 22:37:44 +02007043 if (curproxy->tcp_req.inspect_delay ||
7044 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007045 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007046
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007047 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007048 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007049 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007050 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007051
7052 /* both TCP and HTTP must check switching rules */
7053 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7054 }
7055
7056 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007057 if (curproxy->tcp_req.inspect_delay ||
7058 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7059 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7060
Emeric Brun97679e72010-09-23 17:56:44 +02007061 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7062 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7063
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007064 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007065 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007066 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007067 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007068
7069 /* If the backend does requires RDP cookie persistence, we have to
7070 * enable the corresponding analyser.
7071 */
7072 if (curproxy->options2 & PR_O2_RDPC_PRST)
7073 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7074 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007075 }
7076
7077 /***********************************************************/
7078 /* At this point, target names have already been resolved. */
7079 /***********************************************************/
7080
7081 /* Check multi-process mode compatibility */
7082
7083 if (global.nbproc > 1 && global.stats_fe) {
7084 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7085 unsigned long mask;
7086
7087 mask = nbits(global.nbproc);
7088 if (global.stats_fe->bind_proc)
7089 mask &= global.stats_fe->bind_proc;
7090
7091 if (bind_conf->bind_proc)
7092 mask &= bind_conf->bind_proc;
7093
7094 /* stop here if more than one process is used */
7095 if (popcount(mask) > 1)
7096 break;
7097 }
7098 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7099 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");
7100 }
7101 }
7102
7103 /* Make each frontend inherit bind-process from its listeners when not specified. */
7104 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7105 if (curproxy->bind_proc)
7106 continue;
7107
7108 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7109 unsigned long mask;
7110
7111 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7112 curproxy->bind_proc |= mask;
7113 }
7114
7115 if (!curproxy->bind_proc)
7116 curproxy->bind_proc = ~0UL;
7117 }
7118
7119 if (global.stats_fe) {
7120 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7121 unsigned long mask;
7122
7123 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7124 global.stats_fe->bind_proc |= mask;
7125 }
7126 if (!global.stats_fe->bind_proc)
7127 global.stats_fe->bind_proc = ~0UL;
7128 }
7129
Willy Tarreaub3228c82014-10-01 20:50:17 +02007130 /* propagate bindings from frontends to backends. Don't do it if there
7131 * are any fatal errors as we must not call it with unresolved proxies.
7132 */
7133 if (!cfgerr) {
7134 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7135 if (curproxy->cap & PR_CAP_FE)
7136 propagate_processes(curproxy, NULL);
7137 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007138 }
7139
7140 /* Bind each unbound backend to all processes when not specified. */
7141 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7142 if (curproxy->bind_proc)
7143 continue;
7144 curproxy->bind_proc = ~0UL;
7145 }
7146
7147 /*******************************************************/
7148 /* At this step, all proxies have a non-null bind_proc */
7149 /*******************************************************/
7150
7151 /* perform the final checks before creating tasks */
7152
7153 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7154 struct listener *listener;
7155 unsigned int next_id;
7156 int nbproc;
7157
7158 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007159
Emeric Brunc52962f2012-11-15 18:28:02 +01007160#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007161 /* Configure SSL for each bind line.
7162 * Note: if configuration fails at some point, the ->ctx member
7163 * remains NULL so that listeners can later detach.
7164 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007165 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007166 int alloc_ctx;
7167
Emeric Brunc52962f2012-11-15 18:28:02 +01007168 if (!bind_conf->is_ssl) {
7169 if (bind_conf->default_ctx) {
7170 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7171 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7172 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007173 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007174 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007175 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007176 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007177 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007178 cfgerr++;
7179 continue;
7180 }
7181
Emeric Brun8dc60392014-05-09 13:52:00 +02007182 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007183 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007184 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7185 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");
7186 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007187 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007188 cfgerr++;
7189 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007190 }
7191
Emeric Brunfc0421f2012-09-07 17:30:07 +02007192 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007193 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007194 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007195#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007196
Willy Tarreaue6b98942007-10-29 01:09:36 +01007197 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007198 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007199 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007200 if (!listener->luid) {
7201 /* listener ID not set, use automatic numbering with first
7202 * spare entry starting with next_luid.
7203 */
7204 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7205 listener->conf.id.key = listener->luid = next_id;
7206 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007207 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007208 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007209
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007210 /* enable separate counters */
7211 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7212 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007213 if (!listener->name)
7214 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007215 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007216
Willy Tarreaue6b98942007-10-29 01:09:36 +01007217 if (curproxy->options & PR_O_TCP_NOLING)
7218 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007219 if (!listener->maxconn)
7220 listener->maxconn = curproxy->maxconn;
7221 if (!listener->backlog)
7222 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007223 if (!listener->maxaccept)
7224 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7225
7226 /* we want to have an optimal behaviour on single process mode to
7227 * maximize the work at once, but in multi-process we want to keep
7228 * some fairness between processes, so we target half of the max
7229 * number of events to be balanced over all the processes the proxy
7230 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7231 * used to disable the limit.
7232 */
7233 if (listener->maxaccept > 0) {
7234 if (nbproc > 1)
7235 listener->maxaccept = (listener->maxaccept + 1) / 2;
7236 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7237 }
7238
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007239 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007240 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007241 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007242 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007243
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007244 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7245 listener->options |= LI_O_TCP_RULES;
7246
Willy Tarreaude3041d2010-05-31 10:56:17 +02007247 if (curproxy->mon_mask.s_addr)
7248 listener->options |= LI_O_CHK_MONNET;
7249
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007250 /* smart accept mode is automatic in HTTP mode */
7251 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007252 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007253 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7254 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007255 }
7256
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007257 /* Release unused SSL configs */
7258 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7259 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007260 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007261#ifdef USE_OPENSSL
7262 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007263 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007264 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007265 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007266 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007267#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007268 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007269
Willy Tarreau102df612014-05-07 23:56:38 +02007270 if (nbproc > 1) {
7271 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007272 int count, maxproc = 0;
7273
7274 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7275 count = popcount(bind_conf->bind_proc);
7276 if (count > maxproc)
7277 maxproc = count;
7278 }
7279 /* backends have 0, frontends have 1 or more */
7280 if (maxproc != 1)
7281 Warning("Proxy '%s': in multi-process mode, stats will be"
7282 " limited to process assigned to the current request.\n",
7283 curproxy->id);
7284
Willy Tarreau102df612014-05-07 23:56:38 +02007285 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7286 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7287 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007288 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007289 }
Willy Tarreau102df612014-05-07 23:56:38 +02007290 if (curproxy->appsession_name) {
7291 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7292 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007293 }
Willy Tarreau102df612014-05-07 23:56:38 +02007294 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7295 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7296 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007297 }
7298 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007299
7300 /* create the task associated with the proxy */
7301 curproxy->task = task_new();
7302 if (curproxy->task) {
7303 curproxy->task->context = curproxy;
7304 curproxy->task->process = manage_proxy;
7305 /* no need to queue, it will be done automatically if some
7306 * listener gets limited.
7307 */
7308 curproxy->task->expire = TICK_ETERNITY;
7309 } else {
7310 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7311 curproxy->id);
7312 cfgerr++;
7313 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007314 }
7315
Willy Tarreaufbb78422011-06-05 15:38:35 +02007316 /* automatically compute fullconn if not set. We must not do it in the
7317 * loop above because cross-references are not yet fully resolved.
7318 */
7319 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7320 /* If <fullconn> is not set, let's set it to 10% of the sum of
7321 * the possible incoming frontend's maxconns.
7322 */
7323 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7324 struct proxy *fe;
7325 int total = 0;
7326
7327 /* sum up the number of maxconns of frontends which
7328 * reference this backend at least once or which are
7329 * the same one ('listen').
7330 */
7331 for (fe = proxy; fe; fe = fe->next) {
7332 struct switching_rule *rule;
7333 struct hdr_exp *exp;
7334 int found = 0;
7335
7336 if (!(fe->cap & PR_CAP_FE))
7337 continue;
7338
7339 if (fe == curproxy) /* we're on a "listen" instance */
7340 found = 1;
7341
7342 if (fe->defbe.be == curproxy) /* "default_backend" */
7343 found = 1;
7344
7345 /* check if a "use_backend" rule matches */
7346 if (!found) {
7347 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007348 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007349 found = 1;
7350 break;
7351 }
7352 }
7353 }
7354
7355 /* check if a "reqsetbe" rule matches */
7356 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7357 if (exp->action == ACT_SETBE &&
7358 (struct proxy *)exp->replace == curproxy) {
7359 found = 1;
7360 break;
7361 }
7362 }
7363
7364 /* now we've checked all possible ways to reference a backend
7365 * from a frontend.
7366 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007367 if (!found)
7368 continue;
7369 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007370 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007371 /* we have the sum of the maxconns in <total>. We only
7372 * keep 10% of that sum to set the default fullconn, with
7373 * a hard minimum of 1 (to avoid a divide by zero).
7374 */
7375 curproxy->fullconn = (total + 9) / 10;
7376 if (!curproxy->fullconn)
7377 curproxy->fullconn = 1;
7378 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007379 }
7380
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;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007408
7409 if (curpeers->state == PR_STSTOPPED) {
7410 /* the "disabled" keyword was present */
7411 if (curpeers->peers_fe)
7412 stop_proxy(curpeers->peers_fe);
7413 curpeers->peers_fe = NULL;
7414 }
7415 else if (!curpeers->peers_fe) {
7416 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7417 curpeers->id, localpeer);
7418 }
7419 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007420 last = &curpeers->next;
7421 continue;
7422 }
7423
Willy Tarreau34d05b02015-05-01 20:02:17 +02007424 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007425 p = curpeers->remote;
7426 while (p) {
7427 pb = p->next;
7428 free(p->id);
7429 free(p);
7430 p = pb;
7431 }
7432
7433 /* Destroy and unlink this curpeers section.
7434 * Note: curpeers is backed up into *last.
7435 */
7436 free(curpeers->id);
7437 curpeers = curpeers->next;
7438 free(*last);
7439 *last = curpeers;
7440 }
7441 }
7442
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007443 /* initialize stick-tables on backend capable proxies. This must not
7444 * be done earlier because the data size may be discovered while parsing
7445 * other proxies.
7446 */
7447 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7448 if (curproxy->state == PR_STSTOPPED)
7449 continue;
7450
7451 if (!stktable_init(&curproxy->table)) {
7452 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7453 cfgerr++;
7454 }
7455 }
7456
Willy Tarreau34eb6712011-10-24 18:15:04 +02007457 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007458 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007459 MEM_F_SHARED);
7460
Willy Tarreaubb925012009-07-23 13:36:36 +02007461 if (cfgerr > 0)
7462 err_code |= ERR_ALERT | ERR_FATAL;
7463 out:
7464 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007465}
7466
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007467/*
7468 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7469 * parsing sessions.
7470 */
7471void cfg_register_keywords(struct cfg_kw_list *kwl)
7472{
7473 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7474}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007475
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007476/*
7477 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7478 */
7479void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7480{
7481 LIST_DEL(&kwl->list);
7482 LIST_INIT(&kwl->list);
7483}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007484
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007485/* this function register new section in the haproxy configuration file.
7486 * <section_name> is the name of this new section and <section_parser>
7487 * is the called parser. If two section declaration have the same name,
7488 * only the first declared is used.
7489 */
7490int cfg_register_section(char *section_name,
7491 int (*section_parser)(const char *, int, char **, int))
7492{
7493 struct cfg_section *cs;
7494
7495 cs = calloc(1, sizeof(*cs));
7496 if (!cs) {
7497 Alert("register section '%s': out of memory.\n", section_name);
7498 return 0;
7499 }
7500
7501 cs->section_name = section_name;
7502 cs->section_parser = section_parser;
7503
7504 LIST_ADDQ(&sections, &cs->list);
7505
7506 return 1;
7507}
7508
Willy Tarreaubaaee002006-06-26 02:48:02 +02007509/*
7510 * Local variables:
7511 * c-indent-level: 8
7512 * c-basic-offset: 8
7513 * End:
7514 */